# Localizer
> **Relevant source files**
> * [src/io/github/samera2022/mouse_macros/Localizer.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java)
> * [src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java)
> * [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java)
> * [src/io/github/samera2022/mouse_macros/util/FileUtil.java](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/util/FileUtil.java)
## Purpose and Scope
The `Localizer` utility class provides internationalization (i18n) functionality for the MouseMacros application. It manages loading, caching, and retrieval of localized strings from JSON language files. This system supports seven languages (English, Chinese, Japanese, Korean, Russian, Spanish, and French) and provides automatic system language detection with English fallback.
For information about the language file structure and supported translation keys, see [Language Files and Translation Keys](Language-Files-and-Translation-Keys). For details on how appearance settings control language selection, see [Configuration Files and Settings](Configuration-Files-and-Settings).
**Sources:** [src/io/github/samera2022/mouse_macros/Localizer.java L1-L98](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L1-L98)
---
## Architecture Overview
The `Localizer` operates as a singleton utility with static methods, loading translations at application startup and providing runtime access to localized strings throughout the UI layer.
### System Context Diagram
```mermaid
flowchart TD
StaticInit["Localizer static block"]
EnvDetect["Environment Detection"]
SysLangDetect["System Language Detection"]
DevFiles["Development Mode
lang/*.json files"]
JarFiles["Production Mode
JAR resources"]
LocalizerClass["Localizer"]
TranslationMap["translations Map"]
CurrentLang["currentLang String"]
DevModeFlag["isDevMode boolean"]
RuntimeSwitchFlag["runtimeSwitch boolean"]
LoadMethod["load(String lang)"]
GetMethod["get(String key)"]
IsDevMode["isDevMode()"]
GetCurrentLang["getCurrentLang()"]
SetRuntimeSwitch["setRuntimeSwitch(boolean)"]
ConfigManager["ConfigManager.getAvailableLangs()"]
UIComponents["MainFrame, Dialogs, Listeners"]
SettingsDialog["SettingsDialog
language selection"]
PrimaryLookup["Primary Language Lookup"]
EnglishFallback["English Fallback
en_us.json"]
KeyReturn["Return key if not found"]
EnvDetect --> DevModeFlag
SysLangDetect --> LoadMethod
DevModeFlag --> DevFiles
DevModeFlag --> JarFiles
DevFiles --> LoadMethod
JarFiles --> LoadMethod
LoadMethod --> TranslationMap
LoadMethod --> CurrentLang
GetMethod --> PrimaryLookup
LocalizerClass --> LoadMethod
LocalizerClass --> GetMethod
LocalizerClass --> IsDevMode
LocalizerClass --> GetCurrentLang
LocalizerClass --> SetRuntimeSwitch
ConfigManager --> IsDevMode
ConfigManager --> JarFiles
UIComponents --> GetMethod
SettingsDialog --> LoadMethod
TranslationMap --> GetMethod
CurrentLang --> GetMethod
subgraph subGraph5 ["Fallback Mechanism"]
PrimaryLookup
EnglishFallback
KeyReturn
PrimaryLookup --> EnglishFallback
EnglishFallback --> KeyReturn
end
subgraph subGraph4 ["Integration Points"]
ConfigManager
UIComponents
SettingsDialog
end
subgraph subGraph3 ["API Methods"]
LoadMethod
GetMethod
IsDevMode
GetCurrentLang
SetRuntimeSwitch
end
subgraph subGraph2 ["Localizer Core"]
LocalizerClass
TranslationMap
CurrentLang
DevModeFlag
RuntimeSwitchFlag
end
subgraph subGraph1 ["Language File Sources"]
DevFiles
JarFiles
end
subgraph subGraph0 ["Application Initialization"]
StaticInit
EnvDetect
SysLangDetect
StaticInit --> EnvDetect
StaticInit --> SysLangDetect
end
```
**Sources:** [src/io/github/samera2022/mouse_macros/Localizer.java L1-L98](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L1-L98), [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L79-L132](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L79-L132)
---
## Environment Detection
The `Localizer` determines its operational mode (development or production) during static initialization by checking for the presence of language files in the file system.
### Development vs Production Mode
| Mode | Detection Method | Language File Source | Use Case |
| --- | --- | --- | --- |
| **Development** | Checks if `lang/zh_cn.json` file exists | Reads from `lang/` directory in project | IDE/development environment |
| **Production** | File check fails | Reads from JAR resources `lang/*.json` | Packaged application |
### Environment Detection Logic
```mermaid
flowchart TD
Start["Static Initialization"]
CheckFile["Check File:
new File('lang/zh_cn.json').exists()"]
SetDevMode["isDevMode = true"]
SetProdMode["isDevMode = false"]
DetectSysLang["Detect System Language
Locale.getDefault()"]
NormalizeLang["Normalize language code
replace '-' with '_'"]
CheckLangFile["Language file
exists?"]
UseSysLang["Use system language"]
FallbackEnglish["Fallback to en_us"]
LoadLang["load(currentLang)"]
Start --> CheckFile
CheckFile --> SetDevMode
CheckFile --> SetProdMode
SetDevMode --> DetectSysLang
SetProdMode --> DetectSysLang
DetectSysLang --> NormalizeLang
NormalizeLang --> CheckLangFile
CheckLangFile --> UseSysLang
CheckLangFile --> FallbackEnglish
UseSysLang --> LoadLang
FallbackEnglish --> LoadLang
```
**Code Implementation:**
* **Environment detection**: [src/io/github/samera2022/mouse_macros/Localizer.java L15-L18](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L15-L18)
* **System language detection**: [src/io/github/samera2022/mouse_macros/Localizer.java L20-L32](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L20-L32)
**Sources:** [src/io/github/samera2022/mouse_macros/Localizer.java L15-L33](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L15-L33)
---
## Language Loading Process
The `load(String lang)` method is the core mechanism for loading translation files into memory. It handles both development and production environments differently.
### Loading Flow
```mermaid
sequenceDiagram
participant Caller
participant load(lang)
participant isDevMode check
participant File System
participant ClassLoader
participant Gson Parser
participant translations Map
Caller->>load(lang): load("zh_cn")
load(lang)->>isDevMode check: Check isDevMode
loop [Development Mode]
isDevMode check->>File System: new File("lang/zh_cn.json")
File System->>File System: Check existence
File System-->>load(lang): FileReader
load(lang)->>Gson Parser: fromJson(reader, Map.class)
isDevMode check->>ClassLoader: getResourceAsStream("lang/zh_cn.json")
ClassLoader-->>load(lang): InputStream
load(lang)->>Gson Parser: fromJson(InputStreamReader, Map.class)
end
Gson Parser-->>load(lang): Map
load(lang)->>translations Map: Update translations
load(lang)->>load(lang): currentLang = "zh_cn"
load(lang)-->>Caller: Success
note over load(lang): On exception: translations = empty HashMap
```
### Path Resolution
| Environment | File Path | Access Method |
| --- | --- | --- |
| Development | `/lang/{lang}.json` or `lang/{lang}.json` | `new FileReader(file)` |
| Production | `lang/{lang}.json` (JAR resource) | `ClassLoader.getResourceAsStream(path)` |
**Code Implementation:**
* **Load method signature**: [src/io/github/samera2022/mouse_macros/Localizer.java L47](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L47-L47)
* **Development mode loading**: [src/io/github/samera2022/mouse_macros/Localizer.java L49-L52](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L49-L52)
* **Production mode loading**: [src/io/github/samera2022/mouse_macros/Localizer.java L53-L59](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L53-L59)
* **Error handling**: [src/io/github/samera2022/mouse_macros/Localizer.java L62-L64](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L62-L64)
**Sources:** [src/io/github/samera2022/mouse_macros/Localizer.java L47-L65](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L47-L65)
---
## Translation Retrieval and Fallback Mechanism
The `get(String key)` method implements a two-tier fallback strategy to ensure that UI text is always available, even when translations are incomplete.
### Retrieval Logic Flow
```mermaid
flowchart TD
GetCall["get(key)"]
PrimaryLookup["translations.get(key)"]
CheckValue["value != null?"]
ReturnValue["Return value"]
CheckCurrent["currentLang == 'en_us'?"]
LoadEnglish["Load en_us.json"]
EnglishLookup["enMap.get(key)"]
CheckEnValue["enValue != null?"]
ReturnEnValue["Return enValue"]
ReturnKey["Return key
(untranslated)"]
GetCall --> PrimaryLookup
PrimaryLookup --> CheckValue
CheckValue --> ReturnValue
CheckValue --> CheckCurrent
CheckCurrent --> ReturnKey
CheckCurrent --> LoadEnglish
LoadEnglish --> EnglishLookup
EnglishLookup --> CheckEnValue
CheckEnValue --> ReturnEnValue
CheckEnValue --> ReturnKey
```
### Fallback Behavior Table
| Scenario | Primary Lookup | English Fallback | Final Result |
| --- | --- | --- | --- |
| Key exists in current language | ✓ Found | Not attempted | Localized string |
| Key missing, current is English | ✗ Not found | Not applicable | Key string |
| Key missing, current is not English | ✗ Not found | Attempted | English string or key |
| All lookups fail | ✗ Not found | ✗ Not found | Key string |
**Code Implementation:**
* **Primary lookup**: [src/io/github/samera2022/mouse_macros/Localizer.java L67-L69](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L67-L69)
* **English fallback check**: [src/io/github/samera2022/mouse_macros/Localizer.java L71](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L71-L71)
* **Development mode fallback**: [src/io/github/samera2022/mouse_macros/Localizer.java L73-L79](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L73-L79)
* **Production mode fallback**: [src/io/github/samera2022/mouse_macros/Localizer.java L80-L89](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L80-L89)
* **Final fallback**: [src/io/github/samera2022/mouse_macros/Localizer.java L92](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L92-L92)
**Sources:** [src/io/github/samera2022/mouse_macros/Localizer.java L67-L93](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L67-L93)
---
## Runtime Language Switching
The `Localizer` supports runtime language switching through a control flag and manual reload mechanism.
### Runtime Switch Mechanism
```mermaid
flowchart TD
RuntimeSwitch["runtimeSwitch boolean"]
SetMethod["setRuntimeSwitch(boolean)"]
IsMethod["isRuntimeSwitch()"]
UserAction["User selects new language"]
ConfigUpdate["ConfigManager updates config.lang"]
LoadCall["Localizer.load(newLang)"]
MapUpdate["translations Map updated"]
CurrentLangUpdate["currentLang updated"]
ComponentUtil["ComponentUtil triggers resize"]
FrameAdjust["Frame adjustments based on
readjustFrameMode"]
TextRefresh["UI components re-fetch strings"]
MapUpdate --> ComponentUtil
subgraph subGraph2 ["UI Update"]
ComponentUtil
FrameAdjust
TextRefresh
ComponentUtil --> FrameAdjust
FrameAdjust --> TextRefresh
end
subgraph subGraph1 ["Language Change Process"]
UserAction
ConfigUpdate
LoadCall
MapUpdate
CurrentLangUpdate
UserAction --> ConfigUpdate
ConfigUpdate --> LoadCall
LoadCall --> MapUpdate
LoadCall --> CurrentLangUpdate
end
subgraph subGraph0 ["Control Flag"]
RuntimeSwitch
SetMethod
IsMethod
SetMethod --> RuntimeSwitch
RuntimeSwitch --> IsMethod
end
```
### Runtime Switch API
| Method | Purpose | Usage |
| --- | --- | --- |
| `setRuntimeSwitch(boolean enable)` | Enable/disable runtime switching flag | Called by settings dialog before language change |
| `isRuntimeSwitch()` | Check if runtime switch is active | Used by `ComponentUtil` to determine resize behavior |
| `load(String lang)` | Reload translations for new language | Called after config update |
| `getCurrentLang()` | Get active language code | Used to check current state |
**Code Implementation:**
* **Runtime switch setter**: [src/io/github/samera2022/mouse_macros/Localizer.java L35-L37](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L35-L37)
* **Runtime switch getter**: [src/io/github/samera2022/mouse_macros/Localizer.java L39-L41](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L39-L41)
* **Current language getter**: [src/io/github/samera2022/mouse_macros/Localizer.java L95-L97](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L95-L97)
**Sources:** [src/io/github/samera2022/mouse_macros/Localizer.java L35-L41](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L35-L41), [src/io/github/samera2022/mouse_macros/Localizer.java L95-L97](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L95-L97)
---
## Integration with Configuration System
The `ConfigManager` works with `Localizer` to discover available languages and manage language selection preferences.
### Available Languages Detection
The `ConfigManager.getAvailableLangs()` method enumerates language files using the same environment detection logic as `Localizer`.
```mermaid
flowchart TD
GetLangs["getAvailableLangs()"]
CheckMode["isDevMode()?"]
ListFiles["FileUtil.listFileNames('lang')"]
StripExt1["Strip .json extension"]
GetResURL["getResource('lang/')"]
CheckProtocol["protocol == 'jar'?"]
ParsePath["Parse JAR path"]
OpenJar["new JarFile(jarPath)"]
EnumEntries["Enumerate entries"]
FilterLang["Filter 'lang/*.json'"]
ExtractName["Extract filename"]
ListDir["List directory files"]
FilterJson["Filter .json files"]
StripExt2["Strip extension"]
BuildArray["Build String[] array"]
ReturnLangs["Return available languages"]
GetLangs --> CheckMode
CheckMode --> ListFiles
CheckMode --> GetResURL
StripExt1 --> BuildArray
ExtractName --> BuildArray
StripExt2 --> BuildArray
BuildArray --> ReturnLangs
subgraph subGraph3 ["Production Mode"]
GetResURL
CheckProtocol
GetResURL --> CheckProtocol
CheckProtocol --> ParsePath
CheckProtocol --> ListDir
subgraph subGraph2 ["File Protocol"]
ListDir
FilterJson
StripExt2
ListDir --> FilterJson
FilterJson --> StripExt2
end
subgraph subGraph1 ["JAR Processing"]
ParsePath
OpenJar
EnumEntries
FilterLang
ExtractName
ParsePath --> OpenJar
OpenJar --> EnumEntries
EnumEntries --> FilterLang
FilterLang --> ExtractName
end
end
subgraph subGraph0 ["Development Mode"]
ListFiles
StripExt1
ListFiles --> StripExt1
end
```
### Language Discovery Table
| Environment | Discovery Method | File Pattern |
| --- | --- | --- |
| Development | `FileUtil.listFileNames("lang")` | `lang/*.json` in filesystem |
| Production (JAR) | JAR entry enumeration | Entries matching `lang/*.json` |
| Production (File) | Directory listing | `.json` files in `lang/` directory |
**Code Implementation:**
* **getAvailableLangs() method**: [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L79-L132](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L79-L132)
* **isDevMode() check**: [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L81](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L81-L81)
* **Development mode listing**: [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L82-L91](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L82-L91)
* **JAR entry enumeration**: [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L94-L113](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L94-L113)
* **File protocol handling**: [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L114-L126](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L114-L126)
**Sources:** [src/io/github/samera2022/mouse_macros/manager/ConfigManager.java L79-L132](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/manager/ConfigManager.java#L79-L132), [src/io/github/samera2022/mouse_macros/Localizer.java L43-L45](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L43-L45)
---
## Usage Examples Throughout the Codebase
The `Localizer.get(key)` method is called extensively throughout the UI layer to retrieve localized strings.
### Common Usage Patterns
```mermaid
flowchart TD
MainFrame["MainFrame"]
Dialogs["Various Dialogs"]
Listeners["Event Listeners"]
GetButton["Localizer.get('button.record')"]
GetLog["Localizer.get('log.recording_mouse_pressed')"]
GetTooltip["Localizer.get('tooltip.enable_quick_mode')"]
GetLabel["Localizer.get('label.language')"]
UIKeys["UI Element Labels"]
LogKeys["Log Messages"]
TooltipKeys["Tooltip Text"]
DialogKeys["Dialog Messages"]
MainFrame --> GetButton
MainFrame --> GetLabel
Dialogs --> GetTooltip
Listeners --> GetLog
GetButton --> UIKeys
GetLog --> LogKeys
GetTooltip --> TooltipKeys
GetLabel --> DialogKeys
subgraph subGraph2 ["Translation Keys"]
UIKeys
LogKeys
TooltipKeys
DialogKeys
end
subgraph subGraph1 ["Localizer Usage"]
GetButton
GetLog
GetTooltip
GetLabel
end
subgraph subGraph0 ["UI Components"]
MainFrame
Dialogs
Listeners
end
```
### Example Call Sites
| Component | Key Example | Purpose |
| --- | --- | --- |
| `GlobalMouseListener` | `"recording_key_pressed"` | Log recording events |
| `GlobalMouseListener` | `"log.mouse_left"` | Button name display |
| `GlobalMouseListener` | `"log.recording_scroll_msg1"` | Scroll event logging |
| `MainFrame` | Button labels, menu items | UI text |
| Dialogs | Dialog titles, labels | Settings interface |
**Code Examples:**
* **Key press recording**: [src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java L47](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java#L47-L47)
* **Mouse button names**: [src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java L73](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java#L73-L73)
* **Scroll event logging**: [src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java L125](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java#L125-L125)
**Sources:** [src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java L9](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java#L9-L9), [src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java L47-L48](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java#L47-L48), [src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java L73](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java#L73-L73), [src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java L87](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java#L87-L87), [src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java L125](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/listener/GlobalMouseListener.java#L125-L125)
---
## API Reference
### Static Fields
| Field | Type | Purpose | Access |
| --- | --- | --- | --- |
| `translations` | `Map` | Stores current language key-value pairs | Private |
| `currentLang` | `String` | Currently loaded language code | Private |
| `runtimeSwitch` | `boolean` | Flag for runtime language switching | Private |
| `isDevMode` | `boolean` | Environment detection flag | Private |
### Public Methods
| Method Signature | Return Type | Description |
| --- | --- | --- |
| `load(String lang)` | `void` | Loads translations for specified language |
| `get(String key)` | `String` | Retrieves translation for key with fallback |
| `getCurrentLang()` | `String` | Returns current language code |
| `isDevMode()` | `boolean` | Returns true if in development mode |
| `setRuntimeSwitch(boolean enable)` | `void` | Sets runtime switching flag |
| `isRuntimeSwitch()` | `boolean` | Returns runtime switching flag state |
### Method Details
#### load(String lang)
Loads a language file and populates the `translations` map.
* **Parameters:** * `lang` - Language code (e.g., "en_us", "zh_cn")
* **Behavior:** * In dev mode: reads from `lang/{lang}.json` file * In production: reads from JAR resource `lang/{lang}.json` * Updates `currentLang` on success * Sets `translations` to empty map on error
* **Thread Safety:** Not thread-safe; typically called during initialization or from UI thread
#### get(String key)
Retrieves a localized string for the given key.
* **Parameters:** * `key` - Translation key (e.g., "button.record")
* **Returns:** * Localized string if found in current language * English translation if current language missing key * Key itself if no translation found
* **Thread Safety:** Thread-safe for reading (map is replaced atomically on load)
#### isDevMode()
Checks if running in development environment.
* **Returns:** `true` if `lang/zh_cn.json` file exists, `false` otherwise
* **Usage:** Primarily by `ConfigManager` for language discovery
* **Initialized:** During static initialization
**Sources:** [src/io/github/samera2022/mouse_macros/Localizer.java L1-L98](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L1-L98)
---
## Design Considerations
### Static Initialization
The `Localizer` uses static initialization to ensure translations are available before any UI components are created. The static block:
1. Detects environment (dev vs production)
2. Auto-detects system language via `Locale.getDefault()`
3. Normalizes language codes (replacing `-` with `_`)
4. Checks for language file existence
5. Loads the appropriate language file
This ensures that even early initialization code can safely call `Localizer.get()`.
### Fallback Strategy
The two-tier fallback (current language → English → key) ensures:
* **Graceful degradation**: Missing translations don't break UI
* **Developer visibility**: Untranslated keys appear as-is for easy identification
* **English baseline**: English (`en_us`) serves as complete reference
### Environment Abstraction
The dual-mode (dev/production) design allows:
* **Easy development**: Work with editable JSON files in IDE
* **Proper packaging**: Read from JAR resources in production
* **Consistent API**: Same method calls work in both modes
**Sources:** [src/io/github/samera2022/mouse_macros/Localizer.java L15-L33](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L15-L33), [src/io/github/samera2022/mouse_macros/Localizer.java L47-L65](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L47-L65), [src/io/github/samera2022/mouse_macros/Localizer.java L67-L93](https://github.com/Samera2022/MouseMacros/blob/1eb6620b/src/io/github/samera2022/mouse_macros/Localizer.java#L67-L93)