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.
- package/AGENTS.md +117 -67
- package/AI_ADD_LOCALIZATION_KEY.md +78 -0
- package/AI_ADD_LOCALIZATION_KEY.md.meta +7 -0
- package/AI_API_REFERENCE.md +282 -0
- package/AI_API_REFERENCE.md.meta +7 -0
- package/AI_BEHAVIOR.md +272 -0
- package/AI_BEHAVIOR.md.meta +7 -0
- package/AI_BIND_UI_TEXT.md +97 -0
- package/AI_BIND_UI_TEXT.md.meta +7 -0
- package/AI_IMPORT_TRANSLATIONS.md +84 -0
- package/AI_IMPORT_TRANSLATIONS.md.meta +7 -0
- package/AI_SETUP.md +30 -0
- package/AI_SETUP.md.meta +7 -0
- package/AI_SETUP_LOCALIZATION_MANAGER.md +96 -0
- package/AI_SETUP_LOCALIZATION_MANAGER.md.meta +7 -0
- package/AI_SETUP_LOCALIZATION_SETTINGS.md +199 -0
- package/AI_SETUP_LOCALIZATION_SETTINGS.md.meta +7 -0
- package/AI_SWITCH_LANGUAGE.md +107 -0
- package/AI_SWITCH_LANGUAGE.md.meta +7 -0
- package/AI_USAGE.md +182 -96
- package/CHANGELOG.md +20 -7
- package/Editor/LocalizationComponentWindowsEditor.cs +206 -209
- package/Editor/LocalizationKeyDrawer.cs +121 -121
- package/Editor/LocalizationManagerEditor.cs +265 -232
- package/Editor/LocalizationSettingsEditor.cs +14 -14
- package/README.md +179 -603
- package/Runtime/LocalizationComponent.cs +60 -69
- package/Runtime/LocalizationLanguageItem.cs +42 -42
- package/Runtime/LocalizationManager.cs +293 -293
- package/Runtime/LocalizationSettings.cs +49 -49
- package/Runtime/TMP_LocalizationComponent.cs +33 -42
- package/Samples~/Example/English.xml +10 -0
- package/Samples~/Example/English.xml.meta +7 -0
- package/Samples~/Example/LocalizationSample.csv +6 -0
- package/Samples~/Example/LocalizationSample.csv.meta +7 -0
- package/Samples~/Example/README.md +47 -0
- package/Samples~/Example/README.md.meta +7 -0
- package/Samples~/Example/Vietnamese.xml +10 -0
- package/Samples~/Example/Vietnamese.xml.meta +7 -0
- package/Samples~/Example.meta +8 -0
- package/package.json +19 -8
package/AI_BEHAVIOR.md
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
# AI Behavior Notes For XmobiTea Localization
|
|
2
|
+
|
|
3
|
+
Read this only for lifecycle, source precedence, async refreshes, editor fetch behavior, and key-generation edge cases. Use `AI_SETUP_LOCALIZATION_MANAGER.md` or `AI_SETUP_LOCALIZATION_SETTINGS.md` for setup checklists.
|
|
4
|
+
|
|
5
|
+
## Fast Facts
|
|
6
|
+
|
|
7
|
+
| Question | Answer |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| Does the package create `LocalizationManager`? | No |
|
|
10
|
+
| Does runtime create `LocalizationSettings`? | No |
|
|
11
|
+
| When is settings loaded? | `LocalizationManager.OnInit()` and `GetAllLanguageItem()` |
|
|
12
|
+
| What activates translations? | `LocalizationManager.ChooseLanguage(...)` |
|
|
13
|
+
| Missing-key result? | original key |
|
|
14
|
+
| Runtime reads CSV or Google Sheets? | No |
|
|
15
|
+
| Can one language switch refresh more than once? | Yes, with Addressables or online XML |
|
|
16
|
+
| Does Addressables merge with local XML? | Yes, it adds/overwrites keys |
|
|
17
|
+
| What does online XML do when it completes? | clears the active dictionary, then rebuilds it from the downloaded XML |
|
|
18
|
+
| If Addressables and online XML both exist, what wins last? | whichever async callback finishes later |
|
|
19
|
+
| Are constants discovered at runtime? | No, editor-generated only |
|
|
20
|
+
|
|
21
|
+
## Initialization
|
|
22
|
+
|
|
23
|
+
`LocalizationManager` inherits from `XmobiTea.MiniSingleton.Singleton<LocalizationManager>`.
|
|
24
|
+
|
|
25
|
+
Valid runtime order:
|
|
26
|
+
|
|
27
|
+
1. a loaded scene contains an active `LocalizationManager`;
|
|
28
|
+
2. `Awake()` assigns the singleton cache;
|
|
29
|
+
3. `OnInit()` loads `Resources.Load<LocalizationSettings>("XmobiTea LocalizationSettings")`;
|
|
30
|
+
4. `OnInit()` builds a `SystemLanguage -> LocalizationLanguageItem` dictionary;
|
|
31
|
+
5. app code calls `ChooseLanguage(...)`.
|
|
32
|
+
|
|
33
|
+
Calling static APIs from another component's `Awake()` can fail even if a manager object exists, because the singleton may not have initialized yet.
|
|
34
|
+
|
|
35
|
+
Behavior before activation:
|
|
36
|
+
|
|
37
|
+
- `ChooseLanguage(...)` before singleton init returns `false`;
|
|
38
|
+
- `GetText(...)` before singleton init returns the input key;
|
|
39
|
+
- UI components that enable before language selection display fallback keys until `OnUpdateText` fires.
|
|
40
|
+
|
|
41
|
+
## ChooseLanguage Source Order
|
|
42
|
+
|
|
43
|
+
`ChooseLanguage(systemLanguage)` does this:
|
|
44
|
+
|
|
45
|
+
1. returns `false` if the manager is missing;
|
|
46
|
+
2. returns `false` if `systemLanguage` is not configured;
|
|
47
|
+
3. assigns `currentLanguage`;
|
|
48
|
+
4. clears the active dictionary;
|
|
49
|
+
5. loads local XML synchronously when `LocalizationLanguageItem.xml` exists;
|
|
50
|
+
6. starts Addressables XML load when available and valid;
|
|
51
|
+
7. starts online XML load when `onlineLocalizationUrl` is not empty;
|
|
52
|
+
8. invokes `OnUpdateText` immediately;
|
|
53
|
+
9. invokes `OnUpdateText` again when valid async Addressables or online results complete.
|
|
54
|
+
|
|
55
|
+
Per-source callback effect:
|
|
56
|
+
|
|
57
|
+
| Source | Timing | Dictionary effect |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| local XML `TextAsset` | sync | seeds dictionary |
|
|
60
|
+
| Addressables `xmlRef` | async | adds keys and overwrites duplicates |
|
|
61
|
+
| online URL XML | async | clears dictionary, then rebuilds from downloaded XML |
|
|
62
|
+
|
|
63
|
+
There is no coordination between the two async callbacks. If one language configures both `xmlRef` and `onlineLocalizationUrl`, the callback that finishes later mutates the shared dictionary last.
|
|
64
|
+
|
|
65
|
+
Async stale-result guard:
|
|
66
|
+
|
|
67
|
+
- Addressables and online callbacks apply only when `instance._currentLanguage == thisLanguage`.
|
|
68
|
+
- If the user changed language before the async result completes, the stale result is ignored.
|
|
69
|
+
|
|
70
|
+
Failure behavior:
|
|
71
|
+
|
|
72
|
+
- Addressables failure logs an error and keeps current dictionary content.
|
|
73
|
+
- Online failure logs an error and keeps current dictionary content.
|
|
74
|
+
|
|
75
|
+
## OnUpdateText Semantics
|
|
76
|
+
|
|
77
|
+
For local-only languages, one `ChooseLanguage(...)` call fires `OnUpdateText` once.
|
|
78
|
+
|
|
79
|
+
With async sources, one call may fire two or three times:
|
|
80
|
+
|
|
81
|
+
| Trigger | Event timing |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| local XML | immediate |
|
|
84
|
+
| Addressables XML | async completion |
|
|
85
|
+
| online XML | async completion |
|
|
86
|
+
|
|
87
|
+
Custom listeners must be idempotent.
|
|
88
|
+
|
|
89
|
+
When both async sources are configured, the later refresh order follows callback completion order, not source type priority.
|
|
90
|
+
|
|
91
|
+
Safe subscription:
|
|
92
|
+
|
|
93
|
+
```csharp
|
|
94
|
+
private void OnEnable()
|
|
95
|
+
{
|
|
96
|
+
LocalizationManager.OnUpdateText -= Refresh;
|
|
97
|
+
LocalizationManager.OnUpdateText += Refresh;
|
|
98
|
+
Refresh();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private void OnDisable()
|
|
102
|
+
{
|
|
103
|
+
LocalizationManager.OnUpdateText -= Refresh;
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`OnUpdateText` is a public static `Action`, not a C# `event`. External code can overwrite it. Agents should only generate `+=` and `-=`.
|
|
108
|
+
|
|
109
|
+
## Lookup Behavior
|
|
110
|
+
|
|
111
|
+
`GetText(key)` returns:
|
|
112
|
+
|
|
113
|
+
- `key` when the manager is missing;
|
|
114
|
+
- `key` when `key` is null or empty;
|
|
115
|
+
- `key` when the active dictionary does not contain it;
|
|
116
|
+
- translated dictionary value when found.
|
|
117
|
+
|
|
118
|
+
Fallback-to-key is normal display behavior. Do not treat missing translations as exceptions unless project code adds validation.
|
|
119
|
+
|
|
120
|
+
## UI Component Behavior
|
|
121
|
+
|
|
122
|
+
`LocalizationComponentBase`:
|
|
123
|
+
|
|
124
|
+
- stores `[LocalizationKey] protected string _key`;
|
|
125
|
+
- subscribes to `LocalizationManager.OnUpdateText` on enable;
|
|
126
|
+
- unsubscribes on disable;
|
|
127
|
+
- calls `OnUpdateText()` immediately after subscribing.
|
|
128
|
+
|
|
129
|
+
Targets:
|
|
130
|
+
|
|
131
|
+
| Component | Target | Auto-resolve |
|
|
132
|
+
| --- | --- | --- |
|
|
133
|
+
| `LocalizationComponent` | `UnityEngine.UI.Text` | `GetComponent<Text>()` |
|
|
134
|
+
| `TMP_LocalizationComponent` | `TMP_Text` | `GetComponent<TMP_Text>()` |
|
|
135
|
+
|
|
136
|
+
Use these components for fixed UI text. Generate manual listeners only for dynamic text, non-UI state, or custom rendering.
|
|
137
|
+
|
|
138
|
+
## XML Behavior
|
|
139
|
+
|
|
140
|
+
The parser is structural, not schema-based.
|
|
141
|
+
|
|
142
|
+
Expected shape:
|
|
143
|
+
|
|
144
|
+
```xml
|
|
145
|
+
<?xml version='1.0' encoding='utf-8'?>
|
|
146
|
+
<English>
|
|
147
|
+
<section name='Local'>
|
|
148
|
+
<key name='Home_Title'>Home</key>
|
|
149
|
+
</section>
|
|
150
|
+
</English>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Parser assumptions:
|
|
154
|
+
|
|
155
|
+
- root element is read from `xmlDoc.ChildNodes.Item(1)`, so include the XML declaration;
|
|
156
|
+
- key nodes are nested under section nodes, under the root;
|
|
157
|
+
- each key node has a `name` attribute;
|
|
158
|
+
- text comes from `node.InnerText`;
|
|
159
|
+
- duplicate keys log and later values overwrite earlier values.
|
|
160
|
+
|
|
161
|
+
Runtime replacements after XML read:
|
|
162
|
+
|
|
163
|
+
| Stored text | Runtime text |
|
|
164
|
+
| --- | --- |
|
|
165
|
+
| `\\n` | newline |
|
|
166
|
+
| `<` | `<` |
|
|
167
|
+
| `>` | `>` |
|
|
168
|
+
| `&` | `&` |
|
|
169
|
+
| `'` | `'` |
|
|
170
|
+
| `"` | `"` |
|
|
171
|
+
|
|
172
|
+
Malformed XML, missing declarations, or missing `name` attributes can throw during load.
|
|
173
|
+
|
|
174
|
+
## Editor Fetch Behavior
|
|
175
|
+
|
|
176
|
+
`FetchType` is editor-only:
|
|
177
|
+
|
|
178
|
+
```csharp
|
|
179
|
+
FetchType.None
|
|
180
|
+
FetchType.FromGoogleSheets
|
|
181
|
+
FetchType.FromCsv
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Current constraints:
|
|
185
|
+
|
|
186
|
+
- `Fetch Localization` checks `worksheetKey` only when a Google Sheets fetch type is selected.
|
|
187
|
+
- CSV-only import can leave `worksheetKey` empty.
|
|
188
|
+
- The custom inspector hides `worksheetKey` unless a Google Sheets fetch type is selected.
|
|
189
|
+
- Empty Google sheet-name fields are passed to the fetch executable as default tab names: `local` for local XML and `online` for online XML. The inspector still warns when they are empty.
|
|
190
|
+
- Google sheet tab names are not quoted in the command-line arguments, so names with spaces are unsafe.
|
|
191
|
+
- CSV assets are not null-checked before `.text`.
|
|
192
|
+
- CSV row lengths are not validated before language-column indexing.
|
|
193
|
+
- Local XML target assets are assumed to exist when a `Local-LocalizationFile/<Language>.xml` file is copied back.
|
|
194
|
+
- After every `Fetch Localization` run, the editor copies any existing `Local-LocalizationFile/<Language>.xml` file over the matching language item's assigned local `xml` asset, even when the current local fetch type is `None` or only online output was requested. Clear stale local output files before online-only fetches if local XML must remain untouched.
|
|
195
|
+
- Runtime never reads CSV files.
|
|
196
|
+
|
|
197
|
+
### FromGoogleSheets
|
|
198
|
+
|
|
199
|
+
When either fetch type is `FromGoogleSheets`, the editor:
|
|
200
|
+
|
|
201
|
+
1. finds the package folder in `Library/PackageCache` or `Assets`;
|
|
202
|
+
2. runs the bundled platform `GetLocalization` executable;
|
|
203
|
+
3. passes credentials path, worksheet key, local/online booleans, sheet names, and configured languages; empty sheet names are sent as `local` or `online`;
|
|
204
|
+
4. expects output files under `Local-LocalizationFile/<Language>.xml` and/or `Online-LocalizationFile/<Language>.xml`;
|
|
205
|
+
5. copies existing local output files over each language item's configured local `XML` asset;
|
|
206
|
+
6. refreshes assets;
|
|
207
|
+
7. regenerates `LocalizationConstantId.cs`.
|
|
208
|
+
|
|
209
|
+
Sheet tab names are passed as command-line arguments without quoting. Avoid spaces.
|
|
210
|
+
|
|
211
|
+
### FromCsv
|
|
212
|
+
|
|
213
|
+
When local fetch is `FromCsv`, the editor:
|
|
214
|
+
|
|
215
|
+
1. parses `csvFetchLocalLocalization` with comma delimiter and header removal;
|
|
216
|
+
2. maps column 1 to key and later columns to `localizationLanguageItems` order;
|
|
217
|
+
3. writes `Local-LocalizationFile/<Language>.xml`;
|
|
218
|
+
4. copies existing local output files over each language item's configured local `XML` asset.
|
|
219
|
+
|
|
220
|
+
When online fetch is `FromCsv`, the editor:
|
|
221
|
+
|
|
222
|
+
1. parses `csvFetchOnlineLocalization`;
|
|
223
|
+
2. writes `Online-LocalizationFile/<Language>.xml`;
|
|
224
|
+
3. does not assign those files to a runtime field.
|
|
225
|
+
|
|
226
|
+
Online runtime loading still depends on `LocalizationLanguageItem.onlineLocalizationUrl`.
|
|
227
|
+
|
|
228
|
+
## Generated Constants
|
|
229
|
+
|
|
230
|
+
`Generate LocalizationConstantId.cs`:
|
|
231
|
+
|
|
232
|
+
1. loads `LocalizationSettings`;
|
|
233
|
+
2. reads the first configured language item;
|
|
234
|
+
3. parses that item's local XML;
|
|
235
|
+
4. writes `Assets/XmobiTea-constant/Scripts/LocalizationConstantId.cs`;
|
|
236
|
+
5. creates `public static readonly string` members.
|
|
237
|
+
|
|
238
|
+
Consequences:
|
|
239
|
+
|
|
240
|
+
- keys missing from the first language XML are not generated;
|
|
241
|
+
- runtime-only or online-only keys are not generated unless they also exist in first local XML;
|
|
242
|
+
- generated constants do not update automatically when XML changes;
|
|
243
|
+
- key picker warnings depend on generated constants loaded in assemblies.
|
|
244
|
+
|
|
245
|
+
Field-name conversion:
|
|
246
|
+
|
|
247
|
+
- invalid C# identifier characters become `_`;
|
|
248
|
+
- diacritics are removed;
|
|
249
|
+
- digit-starting names are prefixed with `_`;
|
|
250
|
+
- C# keywords are prefixed with `_`;
|
|
251
|
+
- duplicate generated field names log and later duplicates are skipped.
|
|
252
|
+
|
|
253
|
+
## Correct Mental Model
|
|
254
|
+
|
|
255
|
+
Treat this package as:
|
|
256
|
+
|
|
257
|
+
- scene-authored;
|
|
258
|
+
- explicit-language-selection based;
|
|
259
|
+
- `Resources` configured;
|
|
260
|
+
- XML-backed at runtime;
|
|
261
|
+
- key-based with fallback-to-key display;
|
|
262
|
+
- event-driven for UI refresh;
|
|
263
|
+
- editor-assisted for CSV/Google Sheets import and constant generation.
|
|
264
|
+
|
|
265
|
+
Do not treat it as:
|
|
266
|
+
|
|
267
|
+
- an auto-locale bootstrapper;
|
|
268
|
+
- a runtime CSV reader;
|
|
269
|
+
- a Google Sheets runtime client;
|
|
270
|
+
- an ICU/pluralization formatter;
|
|
271
|
+
- a strict XML schema validator;
|
|
272
|
+
- a compile-time-safe localization database.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# AI Bind UI Text
|
|
2
|
+
|
|
3
|
+
Use this when a task needs to localize fixed UI copy such as labels, titles, descriptions, tabs, button captions, or popup text.
|
|
4
|
+
|
|
5
|
+
## Default Rule
|
|
6
|
+
|
|
7
|
+
Use localization components for fixed UI text.
|
|
8
|
+
|
|
9
|
+
Do not generate a custom script that only does:
|
|
10
|
+
|
|
11
|
+
```csharp
|
|
12
|
+
text.text = LocalizationManager.GetText(key);
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Component Choice
|
|
16
|
+
|
|
17
|
+
| Target | Use |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `UnityEngine.UI.Text` | `LocalizationComponent` |
|
|
20
|
+
| `TMP_Text` | `TMP_LocalizationComponent` |
|
|
21
|
+
|
|
22
|
+
`TMP_LocalizationComponent` exists only when TextMesh Pro support defines `UNITY_USING_TMPRO`.
|
|
23
|
+
|
|
24
|
+
## Bind One Object
|
|
25
|
+
|
|
26
|
+
Checklist:
|
|
27
|
+
|
|
28
|
+
- add the correct localization component to the same `GameObject` as the target text when possible;
|
|
29
|
+
- set `key`;
|
|
30
|
+
- keep the target reference on the component if the text is not on the same object;
|
|
31
|
+
- call `LocalizationManager.ChooseLanguage(...)` during startup so the component receives translated text.
|
|
32
|
+
|
|
33
|
+
Inspector helpers:
|
|
34
|
+
|
|
35
|
+
- `Reload Text` forces one preview refresh;
|
|
36
|
+
- the key dropdown uses generated `LocalizationConstantId` values;
|
|
37
|
+
- missing-key warnings compare the assigned key against generated constants.
|
|
38
|
+
|
|
39
|
+
## Bulk Bind Existing UI
|
|
40
|
+
|
|
41
|
+
Open:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
XmobiTea Tools/Localization/Show LocalizationComponentWindows
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Use the window to:
|
|
48
|
+
|
|
49
|
+
- scan a parent object;
|
|
50
|
+
- add `LocalizationComponent` or `TMP_LocalizationComponent`;
|
|
51
|
+
- assign keys;
|
|
52
|
+
- remove an incorrect localization component.
|
|
53
|
+
|
|
54
|
+
## Dynamic Or Composed Text
|
|
55
|
+
|
|
56
|
+
Use custom code only for:
|
|
57
|
+
|
|
58
|
+
- text built from runtime values;
|
|
59
|
+
- non-UI cached state;
|
|
60
|
+
- custom rendering outside `Text` and `TMP_Text`.
|
|
61
|
+
|
|
62
|
+
Pattern:
|
|
63
|
+
|
|
64
|
+
```csharp
|
|
65
|
+
private void OnEnable()
|
|
66
|
+
{
|
|
67
|
+
LocalizationManager.OnUpdateText -= Refresh;
|
|
68
|
+
LocalizationManager.OnUpdateText += Refresh;
|
|
69
|
+
Refresh();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private void OnDisable()
|
|
73
|
+
{
|
|
74
|
+
LocalizationManager.OnUpdateText -= Refresh;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Key Safety
|
|
79
|
+
|
|
80
|
+
After adding, removing, or renaming keys, run:
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
XmobiTea Tools/Localization/Generate LocalizationConstantId.cs
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Use generated constants when available:
|
|
87
|
+
|
|
88
|
+
```csharp
|
|
89
|
+
localizationComponent.key = LocalizationConstantId.Home_Title;
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Hard No
|
|
93
|
+
|
|
94
|
+
- Do not bind fixed UI copy through one-off scripts when a localization component is enough.
|
|
95
|
+
- Do not assume the component will find a target on another object automatically.
|
|
96
|
+
- Do not rely on key dropdown warnings before constants are generated.
|
|
97
|
+
- Do not forget that components can refresh more than once after one language switch.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# AI Import Translations
|
|
2
|
+
|
|
3
|
+
Use this when translations come from CSV or Google Sheets, or when XML files must be regenerated through editor tooling.
|
|
4
|
+
|
|
5
|
+
## Runtime Rule
|
|
6
|
+
|
|
7
|
+
- runtime never reads CSV or Google Sheets;
|
|
8
|
+
- `Fetch Localization` is editor-only;
|
|
9
|
+
- fetch converts external data into XML and then regenerates `LocalizationConstantId.cs`.
|
|
10
|
+
|
|
11
|
+
## CSV Import
|
|
12
|
+
|
|
13
|
+
Checklist:
|
|
14
|
+
|
|
15
|
+
- import the CSV into Unity as a `TextAsset`;
|
|
16
|
+
- configure `localizationLanguageItems` in the same order as CSV language columns;
|
|
17
|
+
- assign a local XML `TextAsset` to every runtime language item;
|
|
18
|
+
- set `Fetch Type Local Localization` to `FromCsv` when generating local XML;
|
|
19
|
+
- assign `Csv Fetch Local Localization`;
|
|
20
|
+
- set `Fetch Type Online Localization` to `FromCsv` only when generating online XML too;
|
|
21
|
+
- assign `Csv Fetch Online Localization` when online fetch uses CSV;
|
|
22
|
+
- run `XmobiTea Tools/Localization/Fetch Localization`.
|
|
23
|
+
|
|
24
|
+
CSV shape:
|
|
25
|
+
|
|
26
|
+
```text
|
|
27
|
+
Key,English,Vietnamese
|
|
28
|
+
Home_Title,Home,Trang chu
|
|
29
|
+
Home_Subtitle,Welcome,Chao mung
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Rules:
|
|
33
|
+
|
|
34
|
+
- delimiter is comma;
|
|
35
|
+
- first row is header and is skipped;
|
|
36
|
+
- first column is key;
|
|
37
|
+
- every row must have one cell per configured language;
|
|
38
|
+
- use empty cells for blank translations instead of shortening rows.
|
|
39
|
+
|
|
40
|
+
## Google Sheets Import
|
|
41
|
+
|
|
42
|
+
Checklist:
|
|
43
|
+
|
|
44
|
+
- put the spreadsheet id/key in `worksheetKey`;
|
|
45
|
+
- configure `localizationLanguageItems` in the same order as sheet language columns;
|
|
46
|
+
- assign a local XML `TextAsset` to every runtime language item;
|
|
47
|
+
- set `Fetch Type Local Localization` to `FromGoogleSheets` when generating local XML;
|
|
48
|
+
- set `Sheet Name Fetch Local Localization`; empty uses the default executable argument `local`;
|
|
49
|
+
- set `Fetch Type Online Localization` to `FromGoogleSheets` only when generating online XML too;
|
|
50
|
+
- set `Sheet Name Fetch Online Localization` when online fetch uses Google Sheets; empty uses the default executable argument `online`;
|
|
51
|
+
- keep explicit sheet names without spaces;
|
|
52
|
+
- run `XmobiTea Tools/Localization/Fetch Localization`.
|
|
53
|
+
|
|
54
|
+
## Outputs
|
|
55
|
+
|
|
56
|
+
- generated local XML is copied into each assigned local `xml` asset;
|
|
57
|
+
- generated online XML is written under `Online-LocalizationFile/<Language>.xml`;
|
|
58
|
+
- runtime online loading still requires hosting those XML files and assigning `onlineLocalizationUrl`.
|
|
59
|
+
- after any fetch run, existing `Local-LocalizationFile/<Language>.xml` files are copied into assigned local `xml` assets, even if only online output was requested. Remove stale local output files first when local XML must stay unchanged.
|
|
60
|
+
|
|
61
|
+
## When To Regenerate Constants Only
|
|
62
|
+
|
|
63
|
+
Run this instead of full fetch when XML is already up to date and only keys changed:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
XmobiTea Tools/Localization/Generate LocalizationConstantId.cs
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Common Failures
|
|
70
|
+
|
|
71
|
+
| Symptom | Likely cause | Fix |
|
|
72
|
+
| --- | --- | --- |
|
|
73
|
+
| fetch fails for Google Sheets | empty `worksheetKey` | set the spreadsheet id/key |
|
|
74
|
+
| XML generated for wrong language | language order does not match CSV or Sheet columns | reorder `localizationLanguageItems` or source columns |
|
|
75
|
+
| local XML changes during online-only fetch | stale `Local-LocalizationFile/<Language>.xml` exists | remove stale local output files before fetching |
|
|
76
|
+
| online XML never used at runtime | `onlineLocalizationUrl` is empty | host the generated XML and set the URL |
|
|
77
|
+
| constants missing keys after fetch | first configured local XML is incomplete | fix first local XML and regenerate constants |
|
|
78
|
+
|
|
79
|
+
## Hard No
|
|
80
|
+
|
|
81
|
+
- Do not claim CSV or Google Sheets are runtime sources.
|
|
82
|
+
- Do not skip assigning local XML assets when local XML output is expected.
|
|
83
|
+
- Do not shorten translation rows when one language is blank.
|
|
84
|
+
- Do not forget that fetch menu actions are editor-only entrypoints.
|
package/AI_SETUP.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# AI Setup For XmobiTea Localization
|
|
2
|
+
|
|
3
|
+
Use this file only as a setup router. Open the specific setup file below.
|
|
4
|
+
|
|
5
|
+
## Setup Routing
|
|
6
|
+
|
|
7
|
+
| Need | Use |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| Scene object, singleton timing, bootstrap call, persistent manager | `AI_SETUP_LOCALIZATION_MANAGER.md` |
|
|
10
|
+
| Settings asset, language items, XML shape, CSV/Google import, constants | `AI_SETUP_LOCALIZATION_SETTINGS.md` |
|
|
11
|
+
| Switch runtime language after setup | `AI_SWITCH_LANGUAGE.md` |
|
|
12
|
+
| Bind fixed UI text | `AI_BIND_UI_TEXT.md` |
|
|
13
|
+
| Add, rename, or remove a localization key | `AI_ADD_LOCALIZATION_KEY.md` |
|
|
14
|
+
| Import translations from CSV or Google Sheets | `AI_IMPORT_TRANSLATIONS.md` |
|
|
15
|
+
| Choose runtime API after setup | `AI_USAGE.md` |
|
|
16
|
+
| Lifecycle/source precedence edge cases | `AI_BEHAVIOR.md` |
|
|
17
|
+
|
|
18
|
+
## Minimal Runtime Contract
|
|
19
|
+
|
|
20
|
+
- A loaded scene has one active initialized `LocalizationManager`.
|
|
21
|
+
- A `LocalizationSettings` asset loadable as `Resources.Load<LocalizationSettings>("XmobiTea LocalizationSettings")` exists.
|
|
22
|
+
- `localizationLanguageItems` contains the requested `SystemLanguage`.
|
|
23
|
+
- Runtime language items have XML unless deliberately online/addressable-only.
|
|
24
|
+
- App bootstrap calls `LocalizationManager.ChooseLanguage(...)` from `Start()` or later.
|
|
25
|
+
|
|
26
|
+
## Setup Order
|
|
27
|
+
|
|
28
|
+
1. Configure `LocalizationSettings`: `AI_SETUP_LOCALIZATION_SETTINGS.md`.
|
|
29
|
+
2. Add and bootstrap `LocalizationManager`: `AI_SETUP_LOCALIZATION_MANAGER.md`.
|
|
30
|
+
3. Bind UI text or call runtime APIs: `AI_USAGE.md`.
|
package/AI_SETUP.md.meta
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# AI Setup LocalizationManager
|
|
2
|
+
|
|
3
|
+
Use this when a task mentions scene setup, singleton timing, bootstrapping language selection, persistent localization, UI text binding timing, or `[Localization] LocalizationManager instance is null!`.
|
|
4
|
+
|
|
5
|
+
Open smaller task files when setup is already done:
|
|
6
|
+
|
|
7
|
+
- `AI_SWITCH_LANGUAGE.md` for switching runtime language;
|
|
8
|
+
- `AI_BIND_UI_TEXT.md` for binding fixed UI text.
|
|
9
|
+
|
|
10
|
+
## Required Imports
|
|
11
|
+
|
|
12
|
+
```csharp
|
|
13
|
+
using UnityEngine;
|
|
14
|
+
using XmobiTea.MiniLocalization;
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Scene Contract
|
|
18
|
+
|
|
19
|
+
- A loaded scene has one active `LocalizationManager` component.
|
|
20
|
+
- `LocalizationManager.Awake()` has initialized before static APIs are called.
|
|
21
|
+
- `LocalizationSettings` already exists and contains the requested language.
|
|
22
|
+
- App bootstrap calls `LocalizationManager.ChooseLanguage(...)` from `Start()` or later.
|
|
23
|
+
- Do not auto-create the manager in runtime code.
|
|
24
|
+
|
|
25
|
+
## Scene Setup
|
|
26
|
+
|
|
27
|
+
Checklist:
|
|
28
|
+
|
|
29
|
+
- Create a boot-scene `GameObject` named `LocalizationManager`.
|
|
30
|
+
- Add the `LocalizationManager` component.
|
|
31
|
+
- Keep the object active and enabled before localization APIs are used.
|
|
32
|
+
- Add `XmobiTea.MiniSingleton.DontDestroy` only when the manager must survive scene loads.
|
|
33
|
+
- Do not add extra `LocalizationManager` objects in later scenes when using one persistent boot manager.
|
|
34
|
+
- Call `ChooseLanguage(...)` from `Start()` or later.
|
|
35
|
+
|
|
36
|
+
Minimal bootstrap:
|
|
37
|
+
|
|
38
|
+
```csharp
|
|
39
|
+
using UnityEngine;
|
|
40
|
+
using XmobiTea.MiniLocalization;
|
|
41
|
+
|
|
42
|
+
public sealed class LocalizationBootstrap : MonoBehaviour
|
|
43
|
+
{
|
|
44
|
+
[SerializeField] private SystemLanguage startupLanguage = SystemLanguage.English;
|
|
45
|
+
|
|
46
|
+
private void Start()
|
|
47
|
+
{
|
|
48
|
+
LocalizationManager.ChooseLanguage(startupLanguage);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Call Timing
|
|
54
|
+
|
|
55
|
+
Avoid calling localization static APIs from another component's `Awake()` unless script execution order guarantees `LocalizationManager.Awake()` has already run.
|
|
56
|
+
|
|
57
|
+
Prefer:
|
|
58
|
+
|
|
59
|
+
```csharp
|
|
60
|
+
private void Start()
|
|
61
|
+
{
|
|
62
|
+
LocalizationManager.ChooseLanguage(SystemLanguage.English);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
UI components that enable before `ChooseLanguage(...)` can show keys first and refresh after `OnUpdateText` fires.
|
|
67
|
+
|
|
68
|
+
## Component Binding Setup
|
|
69
|
+
|
|
70
|
+
For fixed scene UI:
|
|
71
|
+
|
|
72
|
+
- Use `XmobiTea Tools/Localization/Show LocalizationComponentWindows` to bulk scan a parent object.
|
|
73
|
+
- Add `LocalizationComponent` for `UnityEngine.UI.Text`.
|
|
74
|
+
- Add `TMP_LocalizationComponent` for `TMP_Text` when TextMesh Pro support is enabled.
|
|
75
|
+
- Set `key`.
|
|
76
|
+
- Use components for fixed labels, titles, descriptions, tabs, and button captions.
|
|
77
|
+
- Use custom code only for dynamic/composed text or non-UI state.
|
|
78
|
+
|
|
79
|
+
Inspector tools:
|
|
80
|
+
|
|
81
|
+
| Tool | Effect |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `Reload Text` | force one component refresh |
|
|
84
|
+
| key dropdown | selects generated keys found in loaded `LocalizationConstantId` types |
|
|
85
|
+
| missing-key warning | compares component key against generated constants |
|
|
86
|
+
|
|
87
|
+
Run `Generate LocalizationConstantId.cs` before relying on dropdown warnings. Constants setup lives in `AI_SETUP_LOCALIZATION_SETTINGS.md`.
|
|
88
|
+
|
|
89
|
+
## Manager Setup Errors
|
|
90
|
+
|
|
91
|
+
| Symptom or log | Likely cause | Fix |
|
|
92
|
+
| --- | --- | --- |
|
|
93
|
+
| `[Localization] LocalizationManager instance is null!` | no initialized scene manager | add active manager or call later |
|
|
94
|
+
| `ChooseLanguage(...)` returns `false` | manager missing or language not configured | verify manager and settings language item |
|
|
95
|
+
| UI shows raw keys before startup finishes | components enabled before `ChooseLanguage(...)` | call `ChooseLanguage(...)` in bootstrap and allow refresh |
|
|
96
|
+
| duplicate manager disappears | singleton destroyed later duplicate | keep only one persistent manager |
|