Skip to content

Multi-language Implementation (i18n)

Preface

This article mainly describes how to implement multi-language support in a software application.

Brainstorming (Long-conceived approach)

  1. Use SQLite as the language storage object. The first column uses keys directly in the software, the second column uses Chinese, the third column uses English, and so on.
  2. When loading, first determine the system language. If it's Chinese, load Chinese; if it's Japanese, load Japanese; if it's neither Chinese nor Japanese, load English.
  3. After determining the language to load, read the language data from the database file. For example, if loading Chinese, load the key-value pairs from the first column and the Chinese strings from the second column into an in-memory dictionary. This dictionary always contains only two things: one is the key (used in the program), and the other is the currently loaded language string. When switching to another language, re-read the database file and replace the current dictionary. The advantage of this approach is that dictionary lookups are fast because the dictionary resides in memory, and secondly, it saves memory.

1. Overview

This document aims to describe an efficient and lightweight solution for implementing software internationalization based on an SQLite database. By externalizing language resources into a database and utilizing an in-memory caching mechanism, this solution achieves dynamic switching and support for multiple languages while balancing access speed and memory usage.

2. Data Storage Design

An SQLite database is used as the persistent storage medium for language resources. The database table structure is designed as follows:

  • First Column (Key): Language key, serving as the unique identifier referenced internally by the software. For example: lab_CellVolt1.
  • Subsequent Columns (Locale): Each target language corresponds to a column, with the column name being the language code (e.g., CH for Simplified Chinese, EN for English, JP for Japanese).

Example Data Structure:

KeyCHENJP
lab_CellVolt1电压1CellVolt1セル電圧1
lab_Curr电流Current電流

3. Language Loading and Switching Mechanism

3.1 Initial Language Detection

During the software startup phase, the system automatically detects the operating system's locale setting. The logic flow is as follows:

  1. If the system language is Simplified Chinese (zh-CN), load the CH column data by default.
  2. If the system language is Japanese (ja-JP), load the JP column data by default.
  3. If the system language is neither Chinese nor Japanese, load the EN column data as the default fallback language.

3.2 Runtime Dictionary Loading

To improve query efficiency and avoid frequent disk I/O operations, this solution adopts a "load-on-demand to memory" strategy:

  1. Initialization: Based on the language determined in step 3.1, read all key-value pairs from the SQLite database at once. Specifically, traverse the database and combine the values from the first column (Key) and the corresponding language column into a dictionary object that resides in the application's memory.
    • Dictionary Structure: {Key: LocaleString}. For example, when loading Chinese, the dictionary content would be {"lab_CellVolt1": "电压1", "lab_Curr": "电流"}.
  2. Runtime Query: Whenever the software needs to display text, it performs a quick lookup in this in-memory dictionary. For instance, calling GetString("lab_Curr") returns the string "Current" (if English is active) or the corresponding string in the currently loaded language.
  3. Language Switch: When the user switches the language at runtime, the system clears the current in-memory dictionary and re-executes step 3.2.1, reading the data from the newly specified language column in the SQLite database to build a new dictionary object.

4. Solution Advantages Analysis

  • High Performance: All language resources are loaded into an in-memory dictionary once the language is determined. The hash-based lookup feature of dictionaries ensures extremely high query speeds, avoiding the overhead of database queries each time text is rendered.
  • Low Memory Footprint: Only one dictionary instance is maintained in memory at any time – the mapping between "keys" and the "currently active language". This significantly reduces memory consumption compared to solutions that load all language data simultaneously, making it particularly suitable for resource-constrained environments.
  • Easy Extensibility: To add support for a new language, simply add a new column to the database table and populate it with the corresponding translated texts. No modification to business logic code or recompilation of the software is required.
  • Centralized Data Management: All language resources are centrally stored in a single SQLite file, facilitating version control, translation collaboration, and release management.

This tool cannot replace professional testing equipment. For critical situations, please rely on officially certified tools. This website and its tools were developed personally for learning purposes and are not the official Haixing / Livoltek website.