com.xmobitea.changx.mini-localization 1.4.10 → 1.5.0
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 +7 -2
- package/AI_USAGE.md +13 -1
- package/CHANGELOG.md +7 -0
- package/README.md +170 -25
- package/package.json +5 -5
package/AGENTS.md
CHANGED
|
@@ -16,13 +16,16 @@ Applies to everything inside this package folder.
|
|
|
16
16
|
- UI text updates happen through `LocalizationManager.OnUpdateText`.
|
|
17
17
|
- online localization success clears and rebuilds the active dictionary from the downloaded XML.
|
|
18
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.
|
|
19
21
|
|
|
20
22
|
## Required Mental Model
|
|
21
23
|
|
|
22
24
|
Treat this package as:
|
|
23
25
|
|
|
24
26
|
- a scene-managed localization system,
|
|
25
|
-
- XML-driven translation storage,
|
|
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),
|
|
26
29
|
- key-based lookup plus UI refresh events,
|
|
27
30
|
- editor-assisted setup and code generation.
|
|
28
31
|
|
|
@@ -59,4 +62,6 @@ If an agent writes code against this package:
|
|
|
59
62
|
- it should mention the need for scene setup and settings asset,
|
|
60
63
|
- it should not assume constants are available unless generation is part of the workflow,
|
|
61
64
|
- it should account for repeated `OnUpdateText` when async sources are enabled,
|
|
62
|
-
- it should document any changed XML or load-order semantics in `README.md
|
|
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.
|
package/AI_USAGE.md
CHANGED
|
@@ -13,6 +13,8 @@ Use this file when you want to generate code without reading the runtime impleme
|
|
|
13
13
|
- Addressables optional source: `Yes`
|
|
14
14
|
- Online optional source: `Yes`
|
|
15
15
|
- Generated key constants automatic at runtime: `No`
|
|
16
|
+
- Editor fetch source options: `None`, `FromGoogleSheets`, `FromCsv`
|
|
17
|
+
- CSV is editor-only: parsed to XML by editor tooling, never read at runtime
|
|
16
18
|
|
|
17
19
|
## Exact Rules
|
|
18
20
|
|
|
@@ -44,6 +46,14 @@ Treat `GetText(key)` fallback-to-key as normal behavior, not as an exception cas
|
|
|
44
46
|
|
|
45
47
|
If online localization is enabled and succeeds, assume it replaces the active dictionary content.
|
|
46
48
|
|
|
49
|
+
### Rule 8
|
|
50
|
+
|
|
51
|
+
`FetchType` is an enum with three values: `None`, `FromGoogleSheets`, `FromCsv`. It is set separately for local and online fetch.
|
|
52
|
+
|
|
53
|
+
### Rule 9
|
|
54
|
+
|
|
55
|
+
When `FetchType.FromCsv` is active, the editor reads a `TextAsset` CSV assigned in `LocalizationSettings`, converts it to XML, and writes the result to disk. The runtime never reads CSV directly.
|
|
56
|
+
|
|
47
57
|
## Safe Code Template
|
|
48
58
|
|
|
49
59
|
```csharp
|
|
@@ -72,7 +82,9 @@ Do not generate code that assumes:
|
|
|
72
82
|
- auto-bootstrap of language selection,
|
|
73
83
|
- runtime-generated key constants,
|
|
74
84
|
- null return on missing translation,
|
|
75
|
-
- one single synchronous update when online or addressable sources are involved
|
|
85
|
+
- one single synchronous update when online or addressable sources are involved,
|
|
86
|
+
- CSV files are read at runtime,
|
|
87
|
+
- fetch type is a boolean — it is a `FetchType` enum.
|
|
76
88
|
|
|
77
89
|
## Recommended AI Output Style
|
|
78
90
|
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,13 @@ All notable changes to this package will be documented in this file.
|
|
|
3
3
|
|
|
4
4
|
The format is based on (https://www.npmjs.com/org/xmobitea)
|
|
5
5
|
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
### Added
|
|
8
|
+
- `FetchType` enum (`None`, `FromGoogleSheets`, `FromCsv`) replacing the previous boolean `usingFetch*` fields in `LocalizationSettings`.
|
|
9
|
+
- `CsvParser` editor utility for parsing RFC-4180 CSV files, including quoted fields and embedded newlines.
|
|
10
|
+
- `csvFetchLocalLocalization` and `csvFetchOnlineLocalization` `TextAsset` fields in `LocalizationSettings` for CSV-based fetch.
|
|
11
|
+
- CSV fetch path in `LocalizationManagerEditor`: reads an assigned CSV asset, converts each language column to XML, and writes output to `Local-LocalizationFile/` or `Online-LocalizationFile/`.
|
|
12
|
+
|
|
6
13
|
## [1.0.0] - 2021-04-08
|
|
7
14
|
### Added
|
|
8
15
|
- This is the first release of Chang X plugins, as a Package
|
package/README.md
CHANGED
|
@@ -123,13 +123,16 @@ Loads `LocalizationSettings` again from `Resources` and returns the configured l
|
|
|
123
123
|
Localization XML is parsed using:
|
|
124
124
|
|
|
125
125
|
- `XmlDocument`
|
|
126
|
-
- `xmlDoc.ChildNodes.Item(1)`
|
|
127
|
-
- nested section nodes
|
|
126
|
+
- `xmlDoc.ChildNodes.Item(1)` — selects the root element regardless of its tag name
|
|
127
|
+
- nested section nodes — the parser iterates all children of the root, then all children of each section
|
|
128
128
|
- child nodes with attribute `name`
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
The parser does not validate tag names. Both hand-authored XML and editor-generated XML are accepted as long as the nesting is correct.
|
|
131
|
+
|
|
132
|
+
Hand-authored XML example:
|
|
131
133
|
|
|
132
134
|
```xml
|
|
135
|
+
<?xml version='1.0' encoding='utf-8'?>
|
|
133
136
|
<root>
|
|
134
137
|
<section>
|
|
135
138
|
<item name="SomeKey">Translated text</item>
|
|
@@ -137,6 +140,17 @@ Effective expected shape is:
|
|
|
137
140
|
</root>
|
|
138
141
|
```
|
|
139
142
|
|
|
143
|
+
Editor-generated XML (produced by CSV fetch or key generator) uses the language name as the root tag and `<key>` as the child tag:
|
|
144
|
+
|
|
145
|
+
```xml
|
|
146
|
+
<?xml version='1.0' encoding='utf-8'?>
|
|
147
|
+
<English>
|
|
148
|
+
<section name="Local">
|
|
149
|
+
<key name="SomeKey">Translated text</key>
|
|
150
|
+
</section>
|
|
151
|
+
</English>
|
|
152
|
+
```
|
|
153
|
+
|
|
140
154
|
Important behavior:
|
|
141
155
|
|
|
142
156
|
- key is read from `node.Attributes.GetNamedItem("name").Value`
|
|
@@ -163,10 +177,12 @@ It contains:
|
|
|
163
177
|
|
|
164
178
|
- `worksheetKey`
|
|
165
179
|
- `localizationLanguageItems`
|
|
166
|
-
- `
|
|
167
|
-
- `sheetNameFetchLocalLocalization`
|
|
168
|
-
- `
|
|
169
|
-
- `
|
|
180
|
+
- `fetchTypeLocalLocalization` — `FetchType` enum: `None`, `FromGoogleSheets`, `FromCsv`
|
|
181
|
+
- `sheetNameFetchLocalLocalization` — sheet name used when `FromGoogleSheets`
|
|
182
|
+
- `csvFetchLocalLocalization` — `TextAsset` CSV used when `FromCsv`
|
|
183
|
+
- `fetchTypeOnlineLocalization` — `FetchType` enum: `None`, `FromGoogleSheets`, `FromCsv`
|
|
184
|
+
- `sheetNameFetchOnlineLocalization` — sheet name used when `FromGoogleSheets`
|
|
185
|
+
- `csvFetchOnlineLocalization` — `TextAsset` CSV used when `FromCsv`
|
|
170
186
|
|
|
171
187
|
These fields are mainly used by editor tooling.
|
|
172
188
|
|
|
@@ -247,25 +263,96 @@ Important behavior:
|
|
|
247
263
|
|
|
248
264
|
## Fetch localization
|
|
249
265
|
|
|
250
|
-
|
|
266
|
+
`FetchType` controls where the editor reads source data. Each of local and online can independently set `None`, `FromGoogleSheets`, or `FromCsv`.
|
|
267
|
+
|
|
268
|
+
### FromGoogleSheets
|
|
251
269
|
|
|
252
270
|
1. reads settings,
|
|
253
271
|
2. locates a packaged external executable in `Editor/Tools/GetLocalizationTools`,
|
|
254
272
|
3. passes worksheet key, sheet names, and languages as command-line arguments,
|
|
255
|
-
4. expects XML files under `Local-LocalizationFile/<Language>.xml`,
|
|
273
|
+
4. expects XML files written under `Local-LocalizationFile/<Language>.xml` and/or `Online-LocalizationFile/<Language>.xml`,
|
|
256
274
|
5. copies those files into the asset paths referenced by configured `LocalizationLanguageItem.XML`,
|
|
257
275
|
6. refreshes assets,
|
|
258
276
|
7. regenerates `LocalizationConstantId.cs`.
|
|
259
277
|
|
|
260
|
-
|
|
278
|
+
### FromCsv
|
|
279
|
+
|
|
280
|
+
1. reads the `TextAsset` CSV assigned to `csvFetchLocalLocalization` or `csvFetchOnlineLocalization` in settings,
|
|
281
|
+
2. parses it with `CsvParser` — first row is a header and is skipped, first column is the key, subsequent columns are language values in the same order as `localizationLanguageItems`,
|
|
282
|
+
3. converts each language column to XML and writes files under `Local-LocalizationFile/<Language>.xml` or `Online-LocalizationFile/<Language>.xml`,
|
|
283
|
+
4. copies those XML files into the asset paths referenced by configured `LocalizationLanguageItem.XML`,
|
|
284
|
+
5. refreshes assets,
|
|
285
|
+
6. regenerates `LocalizationConstantId.cs`.
|
|
286
|
+
|
|
287
|
+
CSV is always an editor-only input. The runtime never reads CSV files.
|
|
288
|
+
|
|
289
|
+
Expected CSV layout (columns after key must match the order of `localizationLanguageItems`):
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
key,English,Vietnamese
|
|
293
|
+
Home_Title,Home,Trang Chủ
|
|
294
|
+
Home_Subtitle,Welcome,Chào Mừng
|
|
295
|
+
```
|
|
261
296
|
|
|
262
297
|
## Key picker / scene window
|
|
263
298
|
|
|
264
|
-
|
|
299
|
+
### Key picker drawer
|
|
300
|
+
|
|
301
|
+
Every field tagged with `[LocalizationKey]` (used on `_key` in all localization components) renders a custom property drawer in the Inspector:
|
|
302
|
+
|
|
303
|
+
- **Text field** — the key value can be typed directly.
|
|
304
|
+
- **`▼` dropdown button** — opens an `AdvancedDropdown` listing all string constants from `LocalizationConstantId`. Selecting an entry writes the key to the field.
|
|
305
|
+
- **Red warning label** — appears directly below the field when the current key value is not found in any `LocalizationConstantId` partial class. This indicates the editor generator has not been run or the key was renamed.
|
|
306
|
+
- The available key list is populated by reflecting over all loaded assemblies and is refreshed at most once every 60 seconds.
|
|
307
|
+
|
|
308
|
+
### LocalizationComponent window
|
|
309
|
+
|
|
310
|
+
Accessible from:
|
|
311
|
+
|
|
312
|
+
```text
|
|
313
|
+
XmobiTea Tools/Localization/Show LocalizationComponentWindows
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
or from the `LocalizationManager` inspector button or the `LocalizationSettings` inspector button.
|
|
317
|
+
|
|
318
|
+
The window scans UI text objects under a selected parent GameObject and provides controls to add or remove `LocalizationComponent` instances in bulk.
|
|
319
|
+
|
|
320
|
+
## LocalizationSettings inspector
|
|
321
|
+
|
|
322
|
+
The `LocalizationSettings` asset has a custom inspector that shows fields conditionally based on the selected `FetchType`.
|
|
323
|
+
|
|
324
|
+
### Language list
|
|
325
|
+
|
|
326
|
+
- **Localization Language Length** — integer field that controls the array size of `localizationLanguageItems`. Increase or decrease to add or remove language entries.
|
|
327
|
+
- Each language entry expands to show: `System Language`, `Flag Spr`, local `XML` asset, and (when Addressables is installed) `XMLRef`.
|
|
328
|
+
|
|
329
|
+
### Local fetch section
|
|
330
|
+
|
|
331
|
+
- **Fetch Type Local Localization** — enum: `None`, `FromGoogleSheets`, `FromCsv`.
|
|
332
|
+
- When `FromGoogleSheets`: shows **Sheet Name Fetch Local Localization** field with a hint that the value must not be empty and must not contain spaces.
|
|
333
|
+
- When `FromCsv`: shows **Csv Fetch Local Localization** (`TextAsset`) field with a hint that the file must not be null and must use `,` as delimiter.
|
|
265
334
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
-
|
|
335
|
+
### Online fetch section
|
|
336
|
+
|
|
337
|
+
- **Fetch Type Online Localization** — same enum as above with the same conditional fields.
|
|
338
|
+
|
|
339
|
+
### Shared hints
|
|
340
|
+
|
|
341
|
+
- When either fetch type is `FromCsv`: the inspector displays a live hint showing the expected CSV column order based on the currently configured languages, for example:
|
|
342
|
+
```
|
|
343
|
+
The column in csv must start at Key, English, Vietnamese
|
|
344
|
+
```
|
|
345
|
+
- When either fetch type is `FromGoogleSheets`: shows **Worksheet Key** and a hint about the expected column layout in the Google Sheet.
|
|
346
|
+
|
|
347
|
+
### Action buttons
|
|
348
|
+
|
|
349
|
+
Three buttons are available at the bottom of the `LocalizationSettings` inspector (and also from the `LocalizationManager` inspector):
|
|
350
|
+
|
|
351
|
+
| Button | Action |
|
|
352
|
+
|---|---|
|
|
353
|
+
| `Show LocalizationComponentWindows` | Opens the bulk component assignment window |
|
|
354
|
+
| `Generate LocalizationConstantId.cs` | Parses the first language XML and writes the constants file |
|
|
355
|
+
| `Fetch Localization` | Runs the configured fetch (Google Sheets or CSV) then regenerates constants |
|
|
269
356
|
|
|
270
357
|
## Required Setup
|
|
271
358
|
|
|
@@ -280,18 +367,22 @@ Editor tools provide:
|
|
|
280
367
|
|
|
281
368
|
## UI setup
|
|
282
369
|
|
|
283
|
-
|
|
370
|
+
### LocalizationComponent (UnityEngine.UI.Text)
|
|
371
|
+
|
|
372
|
+
1. Add `LocalizationComponent` to the same GameObject as the `Text` component.
|
|
373
|
+
2. Inspector fields:
|
|
374
|
+
- **Main Txt** — reference to the `UnityEngine.UI.Text` target. If left empty, it is auto-resolved via `GetComponent<Text>()` at both edit time (`OnValidate`) and at runtime.
|
|
375
|
+
- **Key** — the localization key. Uses the key picker drawer: type directly or use the `▼` dropdown. A red warning appears if the key is missing from generated constants.
|
|
376
|
+
3. Click **Reload Text** in the inspector to force a text refresh in the editor without entering Play mode.
|
|
284
377
|
|
|
285
|
-
|
|
286
|
-
2. assign or auto-resolve `Text`
|
|
287
|
-
3. set the localization key
|
|
378
|
+
### TMP_LocalizationComponent (TextMesh Pro)
|
|
288
379
|
|
|
289
|
-
|
|
380
|
+
1. Install the TextMesh Pro package.
|
|
381
|
+
2. Add `TMP_LocalizationComponent` to the same GameObject as the `TMP_Text` component.
|
|
382
|
+
3. Inspector fields match `LocalizationComponent`: **TMP Text** reference and **Key** with the same key picker drawer and warning behavior.
|
|
383
|
+
4. Click **Reload Text** to force a refresh in the editor.
|
|
290
384
|
|
|
291
|
-
|
|
292
|
-
2. add `TMP_LocalizationComponent`
|
|
293
|
-
3. assign or auto-resolve `TMP_Text`
|
|
294
|
-
4. set the localization key
|
|
385
|
+
Both components subscribe to `LocalizationManager.OnUpdateText` in `OnEnable` and unsubscribe in `OnDisable`. They also call `OnUpdateText()` immediately after subscribing so the correct text appears when the object becomes active.
|
|
295
386
|
|
|
296
387
|
## Basic Usage
|
|
297
388
|
|
|
@@ -328,12 +419,66 @@ var text = LocalizationManager.GetText(LocalizationConstantId.Home_Title);
|
|
|
328
419
|
|
|
329
420
|
## React to async updates
|
|
330
421
|
|
|
422
|
+
`LocalizationManager.OnUpdateText` is a static `Action` that fires each time the active translation dictionary has been rebuilt or updated.
|
|
423
|
+
|
|
424
|
+
### When it fires
|
|
425
|
+
|
|
426
|
+
One call to `ChooseLanguage(...)` can cause `OnUpdateText` to fire **more than once**:
|
|
427
|
+
|
|
428
|
+
| Trigger | Fires? |
|
|
429
|
+
|---|---|
|
|
430
|
+
| Local XML loaded synchronously | Yes — always, at the end of `ChooseLanguage(...)` |
|
|
431
|
+
| Addressables XML loaded (async) | Yes — when the async operation completes, if the language has not changed again |
|
|
432
|
+
| Online XML loaded (async) | Yes — when the HTTP request completes, if the language has not changed again |
|
|
433
|
+
|
|
434
|
+
For a project that uses only local XML, `OnUpdateText` fires exactly once per `ChooseLanguage(...)` call. For projects that enable addressable or online sources, expect it to fire two or three times.
|
|
435
|
+
|
|
436
|
+
### When to use it directly vs via LocalizationComponent
|
|
437
|
+
|
|
438
|
+
Use `LocalizationComponent` / `TMP_LocalizationComponent` for UI text objects — they subscribe and unsubscribe automatically and handle the refresh internally.
|
|
439
|
+
|
|
440
|
+
Subscribe to `OnUpdateText` directly when you need to refresh non-UI state, for example a data model, a mesh, or custom rendering that depends on localized strings.
|
|
441
|
+
|
|
442
|
+
### Subscription and unsubscription
|
|
443
|
+
|
|
444
|
+
Always unsubscribe when the subscriber is destroyed or disabled to avoid calling a method on a dead object:
|
|
445
|
+
|
|
446
|
+
```csharp
|
|
447
|
+
using UnityEngine;
|
|
448
|
+
using XmobiTea.MiniLocalization;
|
|
449
|
+
|
|
450
|
+
public sealed class ExampleLocalizationListener : MonoBehaviour
|
|
451
|
+
{
|
|
452
|
+
void OnEnable()
|
|
453
|
+
{
|
|
454
|
+
LocalizationManager.OnUpdateText -= Refresh;
|
|
455
|
+
LocalizationManager.OnUpdateText += Refresh;
|
|
456
|
+
Refresh();
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
void OnDisable()
|
|
460
|
+
{
|
|
461
|
+
LocalizationManager.OnUpdateText -= Refresh;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
void Refresh()
|
|
465
|
+
{
|
|
466
|
+
var title = LocalizationManager.GetText(LocalizationConstantId.Home_Title);
|
|
467
|
+
// apply title to non-UI state
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
The `-=` before `+=` in `OnEnable` prevents duplicate subscriptions if the object is enabled more than once.
|
|
473
|
+
|
|
474
|
+
### Minimal example
|
|
475
|
+
|
|
331
476
|
```csharp
|
|
332
477
|
using XmobiTea.MiniLocalization;
|
|
333
478
|
|
|
334
479
|
LocalizationManager.OnUpdateText += () =>
|
|
335
480
|
{
|
|
336
|
-
|
|
481
|
+
UnityEngine.Debug.Log("Localization updated");
|
|
337
482
|
};
|
|
338
483
|
```
|
|
339
484
|
|
|
@@ -454,5 +599,5 @@ com.xmobitea.changx.mini-localization.editor
|
|
|
454
599
|
## Package Metadata
|
|
455
600
|
|
|
456
601
|
- Package name: `com.xmobitea.changx.mini-localization`
|
|
457
|
-
- Unity version: `
|
|
602
|
+
- Unity version: `2022.3+`
|
|
458
603
|
- License: `Apache-2.0`
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "com.xmobitea.changx.mini-localization",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"displayName": "XmobiTea Localization",
|
|
5
5
|
"description": "XmobiTea Unity Toolkit packages",
|
|
6
|
-
"unity": "
|
|
6
|
+
"unity": "2022.3",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"com.xmobitea.changx.app": "1.
|
|
9
|
-
"com.xmobitea.changx.mini-autogenerate": "1.
|
|
10
|
-
"com.xmobitea.changx.mini-singleton": "1.
|
|
8
|
+
"com.xmobitea.changx.app": "1.5.0",
|
|
9
|
+
"com.xmobitea.changx.mini-autogenerate": "1.5.0",
|
|
10
|
+
"com.xmobitea.changx.mini-singleton": "1.5.0"
|
|
11
11
|
},
|
|
12
12
|
"keywords": [
|
|
13
13
|
"chang x",
|