com.xmobitea.changx.mini-localization 1.5.0 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/AGENTS.md +117 -67
  2. package/AI_ADD_LOCALIZATION_KEY.md +78 -0
  3. package/AI_ADD_LOCALIZATION_KEY.md.meta +7 -0
  4. package/AI_API_REFERENCE.md +282 -0
  5. package/AI_API_REFERENCE.md.meta +7 -0
  6. package/AI_BEHAVIOR.md +272 -0
  7. package/AI_BEHAVIOR.md.meta +7 -0
  8. package/AI_BIND_UI_TEXT.md +97 -0
  9. package/AI_BIND_UI_TEXT.md.meta +7 -0
  10. package/AI_IMPORT_TRANSLATIONS.md +84 -0
  11. package/AI_IMPORT_TRANSLATIONS.md.meta +7 -0
  12. package/AI_SETUP.md +30 -0
  13. package/AI_SETUP.md.meta +7 -0
  14. package/AI_SETUP_LOCALIZATION_MANAGER.md +96 -0
  15. package/AI_SETUP_LOCALIZATION_MANAGER.md.meta +7 -0
  16. package/AI_SETUP_LOCALIZATION_SETTINGS.md +199 -0
  17. package/AI_SETUP_LOCALIZATION_SETTINGS.md.meta +7 -0
  18. package/AI_SWITCH_LANGUAGE.md +107 -0
  19. package/AI_SWITCH_LANGUAGE.md.meta +7 -0
  20. package/AI_USAGE.md +182 -96
  21. package/CHANGELOG.md +20 -7
  22. package/Editor/LocalizationComponentWindowsEditor.cs +206 -209
  23. package/Editor/LocalizationKeyDrawer.cs +121 -121
  24. package/Editor/LocalizationManagerEditor.cs +265 -232
  25. package/Editor/LocalizationSettingsEditor.cs +14 -14
  26. package/README.md +179 -603
  27. package/Runtime/LocalizationComponent.cs +60 -69
  28. package/Runtime/LocalizationLanguageItem.cs +42 -42
  29. package/Runtime/LocalizationManager.cs +293 -293
  30. package/Runtime/LocalizationSettings.cs +49 -49
  31. package/Runtime/TMP_LocalizationComponent.cs +33 -42
  32. package/Samples~/Example/English.xml +10 -0
  33. package/Samples~/Example/English.xml.meta +7 -0
  34. package/Samples~/Example/LocalizationSample.csv +6 -0
  35. package/Samples~/Example/LocalizationSample.csv.meta +7 -0
  36. package/Samples~/Example/README.md +47 -0
  37. package/Samples~/Example/README.md.meta +7 -0
  38. package/Samples~/Example/Vietnamese.xml +10 -0
  39. package/Samples~/Example/Vietnamese.xml.meta +7 -0
  40. package/Samples~/Example.meta +8 -0
  41. package/package.json +19 -8
package/AGENTS.md CHANGED
@@ -1,67 +1,117 @@
1
- # XmobiTea Localization Package Notes
2
-
3
- This file defines the usage contract of this package for AI coding agents and maintainers.
4
-
5
- ## Scope
6
-
7
- Applies to everything inside this package folder.
8
-
9
- ## Hard Rules
10
-
11
- - `LocalizationManager` is a scene-hosted singleton and must exist before static APIs are used.
12
- - `LocalizationSettings` must exist in `Resources` under the configured resource path.
13
- - runtime localization is key-based and dictionary-backed.
14
- - `ChooseLanguage(...)` is the operation that actually populates the active text dictionary.
15
- - `GetText(...)` falls back to the original key when translation is missing.
16
- - UI text updates happen through `LocalizationManager.OnUpdateText`.
17
- - online localization success clears and rebuilds the active dictionary from the downloaded XML.
18
- - generated key constants come from editor tooling, not from runtime discovery.
19
- - `FetchType` controls the editor fetch source: `None`, `FromGoogleSheets`, or `FromCsv`.
20
- - CSV fetch reads a `TextAsset` assigned in settings, parses it with `CsvParser`, and writes XML files to disk. It does not alter the runtime dictionary directly.
21
-
22
- ## Required Mental Model
23
-
24
- Treat this package as:
25
-
26
- - a scene-managed localization system,
27
- - XML-driven translation storage at runtime,
28
- - CSV-driven or Google-Sheets-driven fetch workflow in the editor (CSV is converted to XML before being used at runtime),
29
- - key-based lookup plus UI refresh events,
30
- - editor-assisted setup and code generation.
31
-
32
- Do not treat this package as:
33
-
34
- - an auto-configuring localization framework,
35
- - a strongly typed localization database,
36
- - a schema-validated content pipeline,
37
- - a one-shot synchronous load system when addressable or online sources are enabled.
38
-
39
- ## Correct Usage Pattern
40
-
41
- When generating or reviewing code, assume the valid pattern is:
42
-
43
- 1. Ensure `LocalizationManager` exists in scene.
44
- 2. Ensure `LocalizationSettings` exists in `Resources`.
45
- 3. Configure one or more `LocalizationLanguageItem` entries.
46
- 4. Call `ChooseLanguage(...)` during bootstrap.
47
- 5. Bind UI through localization components or direct `GetText(...)` calls.
48
-
49
- ## Incorrect Assumptions
50
-
51
- These assumptions are false:
52
-
53
- - translations are active immediately just because the manager exists.
54
- - generated constants always exist without editor generation.
55
- - online localization merges into local localization without replacing it.
56
- - `GetText(...)` returns null when a key is missing.
57
-
58
- ## Operational Consequences
59
-
60
- If an agent writes code against this package:
61
-
62
- - it should mention the need for scene setup and settings asset,
63
- - it should not assume constants are available unless generation is part of the workflow,
64
- - it should account for repeated `OnUpdateText` when async sources are enabled,
65
- - it should document any changed XML or load-order semantics in `README.md`,
66
- - when describing the fetch workflow, it should distinguish between `FromGoogleSheets` (runs an external executable) and `FromCsv` (reads a `TextAsset` inside the project and converts it to XML),
67
- - it should never imply that CSV is read at runtime — CSV is an editor-only input format.
1
+ # XmobiTea Localization Agent Guide
2
+
3
+ Scope: everything inside `Assets/XmobiTea Localization`.
4
+
5
+ ## Need-Based Routing
6
+
7
+ Choose by current need. Open the smallest file that answers it.
8
+
9
+ | Need | Use |
10
+ | --- | --- |
11
+ | Choose localization API or generate common runtime code | `AI_USAGE.md` |
12
+ | Switch runtime language, read current language, build language selector | `AI_SWITCH_LANGUAGE.md` |
13
+ | Bind fixed UI text or use the bulk localization window | `AI_BIND_UI_TEXT.md` |
14
+ | Add, rename, or remove a localization key | `AI_ADD_LOCALIZATION_KEY.md` |
15
+ | Import translations from CSV or Google Sheets | `AI_IMPORT_TRANSLATIONS.md` |
16
+ | Setup router | `AI_SETUP.md` |
17
+ | Scene object, singleton timing, bootstrap, persistent manager | `AI_SETUP_LOCALIZATION_MANAGER.md` |
18
+ | Settings asset, language items, XML, CSV/Google import, constants | `AI_SETUP_LOCALIZATION_SETTINGS.md` |
19
+ | Exact signatures, return values, serialized fields, XML shape, editor menus | `AI_API_REFERENCE.md` |
20
+ | Lifecycle, source precedence, async refreshes, fetch edge cases | `AI_BEHAVIOR.md` |
21
+ | Package summary for humans | `README.md` |
22
+ | Missing or conflicting doc detail | source code |
23
+
24
+ ## Hard Rules
25
+
26
+ - `LocalizationManager` is a scene-hosted `Singleton<LocalizationManager>`.
27
+ - The package does not auto-create a missing manager.
28
+ - Static APIs require the singleton to initialize first.
29
+ - The conventional host object name is `LocalizationManager`, but runtime depends on the initialized component.
30
+ - Use `XmobiTea.MiniSingleton.DontDestroy` only when later scenes need the same host.
31
+ - Runtime settings lookup key is `XmobiTea LocalizationSettings`; `Open Settings` creates the asset at `Assets/Resources/XmobiTea LocalizationSettings.asset`.
32
+ - `LocalizationSettings.ResourcesPath` is exactly `XmobiTea LocalizationSettings`.
33
+ - `ChooseLanguage(...)` populates the active dictionary.
34
+ - `GetText(...)` falls back to the original key.
35
+ - `LocalizationComponent` targets `UnityEngine.UI.Text`.
36
+ - `TMP_LocalizationComponent` targets `TMP_Text` and exists only with TextMesh Pro support.
37
+ - Fixed labels, titles, descriptions, tabs, and button captions should use localization components.
38
+ - `LocalizationManager.OnUpdateText` is a public static `Action`; subscribe with `+=`/`-=` and never overwrite it.
39
+ - Local XML loads synchronously first.
40
+ - Addressables XML can add/overwrite keys after async load completes.
41
+ - Successful online XML clears and replaces the active dictionary.
42
+ - If one language configures both Addressables XML and online XML, both async loads run and the callback that finishes later mutates the dictionary last.
43
+ - `OnUpdateText` can fire more than once for one `ChooseLanguage(...)` call.
44
+ - Runtime never reads CSV or Google Sheets.
45
+ - `fetchType` is editor-only: `None`, `FromGoogleSheets`, `FromCsv`.
46
+ - `worksheetKey` is required only when either fetch type is `FromGoogleSheets`.
47
+ - Empty Google sheet-name fields are sent to the fetch executable as `local` or `online`; explicit sheet names must avoid spaces.
48
+ - CSV rows must include `Key` plus one cell per configured language.
49
+ - After any fetch run, existing `Local-LocalizationFile/<Language>.xml` files are copied into assigned local XML assets, even during online-only fetches.
50
+ - Generated constants come from editor tooling, not runtime discovery.
51
+ - Generated `LocalizationConstantId` members are `public static readonly string`.
52
+ - The generator reads keys from the first configured language item's local XML.
53
+
54
+ ## Do Not Assume
55
+
56
+ - `LocalizationManager` or `LocalizationSettings` will be created at runtime.
57
+ - Translations are active before `ChooseLanguage(...)`.
58
+ - A missing key returns `null`.
59
+ - One language switch means exactly one `OnUpdateText` call.
60
+ - Online XML merges with local XML.
61
+ - CSV or Google Sheets are runtime data sources.
62
+ - Generated constants are type-safe or auto-updated.
63
+ - Keys missing from the first local XML will generate constants.
64
+ - Nonexistent APIs exist: `SetLanguage`, `CurrentLanguage`, `GetLocalizedText`, `ReloadLanguage`, `FormatText`, `HasKey`.
65
+
66
+ ## Code Generation Guidance
67
+
68
+ - Use `using XmobiTea.MiniLocalization;`.
69
+ - Add `using XmobiTea.MiniLocalization.Core;` only when declaring `LocalizationLanguageItem`.
70
+ - Prefer generated `LocalizationConstantId` values when the generated file exists and is current.
71
+ - Use raw key strings in fresh setups until constants are generated.
72
+ - Put language selection in `Start()` or later unless execution order guarantees manager initialization.
73
+ - Generate scene setup instructions instead of constructing a manager from code.
74
+ - Use `LocalizationComponent` / `TMP_LocalizationComponent` for fixed UI text.
75
+ - Generate custom text refresh code only for dynamic/composed text, non-UI state, or custom rendering.
76
+ - Custom listeners must unsubscribe and must tolerate repeated refreshes.
77
+ - Treat fallback-to-key display as normal runtime behavior.
78
+ - Before using constants, verify the first configured language XML contains the complete key set.
79
+ - Use `Samples~/Example` as the known-good CSV/XML shape.
80
+
81
+ ## Setup Contract
82
+
83
+ When generated code depends on localization, require:
84
+
85
+ 1. A loaded scene contains one active `LocalizationManager`.
86
+ 2. Static APIs run after `LocalizationManager.Awake()`.
87
+ 3. A `LocalizationSettings` asset loadable as `Resources.Load<LocalizationSettings>("XmobiTea LocalizationSettings")` exists.
88
+ 4. `localizationLanguageItems` contains the requested language.
89
+ 5. Runtime language items have local XML unless deliberately online/addressable-only.
90
+ 6. Bootstrap calls `ChooseLanguage(...)`.
91
+ 7. Fixed UI text uses localization components.
92
+ 8. Constants are regenerated after key changes.
93
+ 9. Fetch workflows verify assigned CSV assets, local XML targets, Google `worksheetKey`, and complete language columns.
94
+
95
+ ## Maintenance Checklist
96
+
97
+ If changing resource paths, manager lifecycle, XML parsing, source precedence, generated constants, editor fetch behavior, component binding, or event semantics, update these together:
98
+
99
+ - `Runtime/LocalizationManager.cs`
100
+ - `Runtime/LocalizationSettings.cs`
101
+ - `Runtime/LocalizationLanguageItem.cs`
102
+ - `Runtime/LocalizationComponent.cs`
103
+ - `Runtime/TMP_LocalizationComponent.cs`
104
+ - `Editor/LocalizationManagerEditor.cs`
105
+ - `Editor/LocalizationSettingsEditor.cs`
106
+ - `Editor/LocalizationKeyDrawer.cs`
107
+ - `AI_USAGE.md`
108
+ - `AI_SWITCH_LANGUAGE.md`
109
+ - `AI_BIND_UI_TEXT.md`
110
+ - `AI_ADD_LOCALIZATION_KEY.md`
111
+ - `AI_IMPORT_TRANSLATIONS.md`
112
+ - `AI_SETUP.md`
113
+ - `AI_SETUP_LOCALIZATION_MANAGER.md`
114
+ - `AI_SETUP_LOCALIZATION_SETTINGS.md`
115
+ - `AI_API_REFERENCE.md`
116
+ - `AI_BEHAVIOR.md`
117
+ - `README.md`
@@ -0,0 +1,78 @@
1
+ # AI Add Localization Key
2
+
3
+ Use this when a task adds, renames, or removes a localization key, or when `LocalizationConstantId` is missing or stale.
4
+
5
+ ## Source Of Truth
6
+
7
+ Choose one source of truth and update that source first:
8
+
9
+ - CSV or Google Sheets when the project imports translations through `Fetch Localization`;
10
+ - local XML files when the project edits runtime XML directly.
11
+
12
+ The first configured language item's local XML must contain the full key set because constant generation reads that file only.
13
+
14
+ ## Add A Key
15
+
16
+ Checklist:
17
+
18
+ - add the key to the source of truth;
19
+ - if editing XML directly, add the key to every runtime language XML;
20
+ - keep XML in the runtime parser shape;
21
+ - regenerate constants;
22
+ - update `LocalizationComponent`, `TMP_LocalizationComponent`, and scripts to use the new key.
23
+
24
+ Minimal XML entry:
25
+
26
+ ```xml
27
+ <key name='Home_Title'>Home</key>
28
+ ```
29
+
30
+ ## Rename A Key
31
+
32
+ Checklist:
33
+
34
+ - rename the key in the source of truth;
35
+ - update every affected XML or translation row;
36
+ - regenerate constants;
37
+ - update all component keys and script references;
38
+ - remove old key usages so UI does not fall back to the old raw key string.
39
+
40
+ ## Remove A Key
41
+
42
+ Checklist:
43
+
44
+ - delete the key from the source of truth;
45
+ - regenerate constants;
46
+ - remove or replace every component and code reference to that key.
47
+
48
+ ## Regenerate Constants
49
+
50
+ Run:
51
+
52
+ ```text
53
+ XmobiTea Tools/Localization/Generate LocalizationConstantId.cs
54
+ ```
55
+
56
+ Generated file:
57
+
58
+ ```text
59
+ Assets/XmobiTea-constant/Scripts/LocalizationConstantId.cs
60
+ ```
61
+
62
+ Use raw strings temporarily when constants are intentionally not regenerated yet.
63
+
64
+ ## Verify
65
+
66
+ Checklist:
67
+
68
+ - run `ChooseLanguage(...)`;
69
+ - confirm `LocalizationManager.GetText(key)` returns translated text instead of the raw key;
70
+ - confirm fixed UI text refreshes;
71
+ - confirm the generated constant exists when code uses `LocalizationConstantId.*`.
72
+
73
+ ## Hard No
74
+
75
+ - Do not add a key only to a non-first language XML and expect a constant to generate.
76
+ - Do not rename keys in code only.
77
+ - Do not leave stale component keys after a rename or delete.
78
+ - Do not assume runtime discovers new constants automatically.
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 9c3b91e223da4115ba42193b18265bc0
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,282 @@
1
+ # AI API Reference For XmobiTea Localization
2
+
3
+ Read this only when exact signatures, return values, serialized fields, XML shape, or editor menu names matter. Use `AI_SETUP_LOCALIZATION_MANAGER.md` for manager setup and `AI_SETUP_LOCALIZATION_SETTINGS.md` for settings/import preflight.
4
+
5
+ Required imports for runtime usage:
6
+
7
+ ```csharp
8
+ using UnityEngine;
9
+ using XmobiTea.MiniLocalization;
10
+ ```
11
+
12
+ Additional import only when code declares `LocalizationLanguageItem` directly:
13
+
14
+ ```csharp
15
+ using XmobiTea.MiniLocalization.Core;
16
+ ```
17
+
18
+ ## LocalizationManager API
19
+
20
+ | Signature | Returns | Use for | Missing manager |
21
+ | --- | --- | --- | --- |
22
+ | `public static bool ChooseLanguage(SystemLanguage systemLanguage)` | `true` on accepted language, otherwise `false` | activate or switch language | logs error and returns `false` |
23
+ | `public static string GetText(string key)` | translated text or original `key` | direct string lookup | returns `key` |
24
+ | `public static LocalizationLanguageItem GetCurrentLanguage()` | active item or `null` | inspect selected language | logs error and returns `null` |
25
+ | `public static LocalizationLanguageItem[] GetAllLanguageItem()` | configured items or `null` | show language choices | logs error and returns `null` |
26
+ | `public static string GetTextWithoutBOM(TextAsset textAsset)` | text content | helper for XML `TextAsset` parsing | no manager needed; `textAsset` must be non-null |
27
+ | `public static Action OnUpdateText` | static `Action` field | refresh custom state after dictionary updates | no automatic guard |
28
+
29
+ `ChooseLanguage(...)` returns `false` when the requested `SystemLanguage` is not configured.
30
+
31
+ `GetAllLanguageItem()` reloads `LocalizationSettings` from `Resources`; it does not return a cached copy from the active language dictionary.
32
+
33
+ `OnUpdateText` is a public static `Action` field, not a C# `event`. Subscribe with `+=` and unsubscribe with `-=`. Do not assign it with `=` or set it to `null`.
34
+
35
+ ## Component API
36
+
37
+ | Type | Target | Use for | Key field |
38
+ | --- | --- | --- | --- |
39
+ | `LocalizationComponentBase : MonoBehaviour` | abstract | shared event subscription and key storage | `[LocalizationKey] protected string _key` |
40
+ | `LocalizationComponent : LocalizationComponentBase` | `UnityEngine.UI.Text` | UGUI text binding | `key` property |
41
+ | `TMP_LocalizationComponent : LocalizationComponentBase` | `TMP_Text` | TextMesh Pro binding | `key` property |
42
+
43
+ `TMP_LocalizationComponent` is compiled only when `UNITY_USING_TMPRO` is defined by the package asmdef version define for `com.unity.textmeshpro`.
44
+
45
+ `LocalizationComponentBase` exposes:
46
+
47
+ ```csharp
48
+ public string key { get; set; }
49
+ public virtual void OnUpdateText();
50
+ ```
51
+
52
+ Lifecycle behavior:
53
+
54
+ - `OnEnable()` removes then adds `OnUpdateText` to `LocalizationManager.OnUpdateText`.
55
+ - `OnEnable()` immediately calls `OnUpdateText()`.
56
+ - `OnDisable()` unsubscribes.
57
+
58
+ `LocalizationComponent` auto-fills its target only in `OnValidate()` when the serialized target is empty and the component sits on the same object as `Text`. The same pattern applies to `TMP_LocalizationComponent`.
59
+
60
+ ## LocalizationSettings API
61
+
62
+ ```csharp
63
+ public enum FetchType
64
+ {
65
+ None = 0,
66
+ FromGoogleSheets = 1,
67
+ FromCsv = 2,
68
+ }
69
+
70
+ public class LocalizationSettings : ScriptableObject
71
+ {
72
+ public const string ResourcesPath = "XmobiTea LocalizationSettings";
73
+ public string worksheetKey { get; }
74
+ public LocalizationLanguageItem[] localizationLanguageItems { get; }
75
+ public FetchType fetchTypeLocalLocalization { get; }
76
+ public string sheetnameFetchLocalLocalization { get; }
77
+ public TextAsset csvFetchLocalLocalization { get; }
78
+ public FetchType fetchTypeOnlineLocalization { get; }
79
+ public string sheetnameFetchOnlineLocalization { get; }
80
+ public TextAsset csvFetchOnlineLocalization { get; }
81
+ }
82
+ ```
83
+
84
+ Serialized fields in the asset:
85
+
86
+ | Inspector field | Runtime property | Used by |
87
+ | --- | --- | --- |
88
+ | `_worksheetKey` | `worksheetKey` | editor Google Sheets fetch; required when either fetch type is `FromGoogleSheets` |
89
+ | `_localizationLanguageItems` | `localizationLanguageItems` | runtime language registry |
90
+ | `_fetchTypeLocalLocalization` | `fetchTypeLocalLocalization` | editor local import |
91
+ | `_sheetNameFetchLocalLocalization` | `sheetnameFetchLocalLocalization` | editor Google Sheets local import |
92
+ | `_csvFetchLocalLocalization` | `csvFetchLocalLocalization` | editor CSV local import |
93
+ | `_fetchTypeOnlineLocalization` | `fetchTypeOnlineLocalization` | editor online-file import |
94
+ | `_sheetNameFetchOnlineLocalization` | `sheetnameFetchOnlineLocalization` | editor Google Sheets online import |
95
+ | `_csvFetchOnlineLocalization` | `csvFetchOnlineLocalization` | editor CSV online import |
96
+
97
+ Default asset path created by `Open Settings`:
98
+
99
+ ```text
100
+ Assets/Resources/XmobiTea LocalizationSettings.asset
101
+ ```
102
+
103
+ Runtime load:
104
+
105
+ ```csharp
106
+ Resources.Load<LocalizationSettings>(LocalizationSettings.ResourcesPath)
107
+ ```
108
+
109
+ ## LocalizationSettings Inspector Setup
110
+
111
+ Use this checklist when generating setup instructions:
112
+
113
+ | Inspector field | Required when | Value rule |
114
+ | --- | --- | --- |
115
+ | `Localization Language Length` | always | inspector-only size control that resizes `_localizationLanguageItems` |
116
+ | `systemLanguage` | always per language | Unity `SystemLanguage` value |
117
+ | `flagSpr` | optional | display icon only |
118
+ | `xml` | normal runtime local XML | assign an existing XML `TextAsset` asset |
119
+ | `xmlRef` | optional Addressables runtime XML | shown only when Addressables is installed |
120
+ | `onlineLocalizationUrl` | optional online runtime XML | URL must return parser-compatible XML |
121
+ | `fetchTypeLocalLocalization` | editor import | `None`, `FromGoogleSheets`, or `FromCsv` |
122
+ | `sheetNameFetchLocalLocalization` | local `FromGoogleSheets` | Google Sheet tab name; empty is sent to the fetch executable as `local`; avoid spaces |
123
+ | `csvFetchLocalLocalization` | local `FromCsv` | CSV `TextAsset` imported into Unity |
124
+ | `fetchTypeOnlineLocalization` | editor import | `None`, `FromGoogleSheets`, or `FromCsv` |
125
+ | `sheetNameFetchOnlineLocalization` | online `FromGoogleSheets` | Google Sheet tab name; empty is sent to the fetch executable as `online`; avoid spaces |
126
+ | `csvFetchOnlineLocalization` | online `FromCsv` | CSV `TextAsset` imported into Unity |
127
+ | `worksheetKey` | any `FromGoogleSheets` fetch | non-empty Google spreadsheet id/key |
128
+
129
+ After any `Fetch Localization` run, the editor copies each existing `Local-LocalizationFile/<Language>.xml` file into the matching configured language item's assigned `XML` asset path. Create placeholder XML assets and assign them before fetching. Remove stale `Local-LocalizationFile` outputs before online-only fetches if the assigned local XML assets must not be overwritten.
130
+
131
+ Inspector visibility: `Worksheet Key` is shown only when at least one fetch type is `FromGoogleSheets`. CSV-only import does not require `worksheetKey`.
132
+
133
+ ## Import Data Shape
134
+
135
+ Google Sheet and CSV import use the same column model:
136
+
137
+ ```text
138
+ Key,English,Vietnamese
139
+ Home_Title,Home,Trang chu
140
+ Home_Subtitle,Welcome,Chao mung
141
+ ```
142
+
143
+ Rules:
144
+
145
+ - first row is header;
146
+ - first column is key;
147
+ - subsequent columns map to `localizationLanguageItems` order;
148
+ - column names should match the intended languages for human clarity;
149
+ - every data row must contain `Key` plus one cell per configured language;
150
+ - empty values generate empty XML text nodes;
151
+ - CSV delimiter is comma.
152
+
153
+ `Fetch Localization` is editor-only. It converts external data into XML and regenerates constants; runtime reads XML, Addressables XML, or online XML URL only.
154
+
155
+ ## LocalizationLanguageItem API
156
+
157
+ Namespace:
158
+
159
+ ```csharp
160
+ XmobiTea.MiniLocalization.Core
161
+ ```
162
+
163
+ Shape:
164
+
165
+ ```csharp
166
+ public class LocalizationLanguageItem
167
+ {
168
+ public SystemLanguage systemLanguage { get; }
169
+ public Sprite flagSpr { get; }
170
+ public TextAsset xml { get; set; }
171
+ public string onlineLocalizationUrl { get; set; }
172
+ }
173
+ ```
174
+
175
+ When Addressables is installed:
176
+
177
+ ```csharp
178
+ public AssetReferenceT<TextAsset> xmlRef { get; set; }
179
+ ```
180
+
181
+ One item can provide local XML, optional Addressables XML, and optional online XML URL for the same language.
182
+
183
+ If both `xmlRef` and `onlineLocalizationUrl` are configured, both async loads run independently. The callback that finishes later mutates the active dictionary last.
184
+
185
+ ## Editor Menus
186
+
187
+ | Menu | Effect |
188
+ | --- | --- |
189
+ | `XmobiTea Tools/Localization/Open Settings` | creates or selects `Assets/Resources/XmobiTea LocalizationSettings.asset` |
190
+ | `XmobiTea Tools/Localization/Show LocalizationComponentWindows` | opens bulk UI text binding window |
191
+ | `XmobiTea Tools/Localization/Generate LocalizationConstantId.cs` | generates constants from the first language item's local XML |
192
+ | `XmobiTea Tools/Localization/Fetch Localization` | imports local/online XML files from configured editor sources, copies any existing local output files into assigned XML assets, then regenerates constants |
193
+
194
+ Inspector buttons on `LocalizationManager` and `LocalizationSettings` mirror the window, generate, and fetch actions.
195
+
196
+ ## Generated Constants
197
+
198
+ Runtime package file:
199
+
200
+ ```csharp
201
+ namespace XmobiTea.MiniLocalization
202
+ {
203
+ public partial class LocalizationConstantId { }
204
+ }
205
+ ```
206
+
207
+ Generated file path:
208
+
209
+ ```text
210
+ Assets/XmobiTea-constant/Scripts/LocalizationConstantId.cs
211
+ ```
212
+
213
+ Generated shape:
214
+
215
+ ```csharp
216
+ namespace XmobiTea.MiniLocalization
217
+ {
218
+ public partial class LocalizationConstantId
219
+ {
220
+ public static readonly string Home_Title = "Home_Title";
221
+ }
222
+ }
223
+ ```
224
+
225
+ Generator behavior:
226
+
227
+ - reads only the first configured language item's local XML;
228
+ - converts invalid C# field-name characters to `_`;
229
+ - removes diacritics;
230
+ - prefixes digit-starting names and C# keywords with `_`;
231
+ - logs duplicate generated field names and skips later duplicates.
232
+
233
+ Generated members are `public static readonly string`, not `const`.
234
+
235
+ ## XML Shape
236
+
237
+ Runtime parser accepts any root and section tag names as long as the document has the expected node order, keys are two levels below the root, and each key node has a `name` attribute.
238
+
239
+ Minimal valid XML:
240
+
241
+ ```xml
242
+ <?xml version='1.0' encoding='utf-8'?>
243
+ <English>
244
+ <section name='Local'>
245
+ <key name='Home_Title'>Home</key>
246
+ </section>
247
+ </English>
248
+ ```
249
+
250
+ Parser rules:
251
+
252
+ - expects the root element at `xmlDoc.ChildNodes.Item(1)`, so generated or hand-authored XML should include the XML declaration;
253
+ - reads `xmlDoc.ChildNodes.Item(1)` as root;
254
+ - loops each section node under root;
255
+ - loops each key node under each section;
256
+ - reads key from `node.Attributes.GetNamedItem("name").Value`;
257
+ - reads text from `node.InnerText`;
258
+ - logs duplicate keys and overwrites with the later value.
259
+
260
+ Text replacements after XML read:
261
+
262
+ | Stored text | Runtime text |
263
+ | --- | --- |
264
+ | `\\n` | newline |
265
+ | `&lt;` | `<` |
266
+ | `&gt;` | `>` |
267
+ | `&#38;` | `&` |
268
+ | `&#39;` | `'` |
269
+ | `&#34;` | `"` |
270
+
271
+ ## Error And Fallback Guards
272
+
273
+ - Missing manager: `ChooseLanguage` returns `false`; `GetText` returns the input key; language getters return `null`.
274
+ - Missing settings during manager init: logs `[Localization] Missing XmobiTea LocalizationSettings` and no language registry is built.
275
+ - Missing language in settings: `ChooseLanguage(...)` logs an error and returns `false`.
276
+ - Missing key: `GetText(key)` returns `key`.
277
+ - Empty key: `GetText(key)` returns `key`.
278
+ - Duplicate XML key: logs an error and overwrites with the later value.
279
+ - Missing local XML: local sync load is skipped; optional Addressables or online sources may still update later if configured.
280
+ - Missing first language XML during constant generation: generator can throw while reading or parsing.
281
+ - Missing CSV asset or missing CSV language columns during fetch: editor code can throw before generating XML.
282
+ - Stale `Local-LocalizationFile/<Language>.xml` files can be copied into assigned local XML assets by any later fetch run, including online-only fetches.
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 19e4dcbe1d834c71a35f28c173c7f46d
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant: