locadex 0.0.1 → 0.0.2-alpha.3
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/.locadex-mcp-stdio.json +9 -0
- package/.locadex-mcp.json +8 -0
- package/LICENSE.md +1 -1
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +59 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/i18n.d.ts +2 -0
- package/dist/commands/i18n.d.ts.map +1 -0
- package/dist/commands/i18n.js +215 -0
- package/dist/commands/i18n.js.map +1 -0
- package/dist/commands/setup.d.ts +2 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +89 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -68
- package/dist/index.js.map +1 -1
- package/dist/logging/console.d.ts +45 -0
- package/dist/logging/console.d.ts.map +1 -0
- package/dist/logging/console.js +134 -0
- package/dist/logging/console.js.map +1 -0
- package/dist/logging/constructInfo.d.ts +3 -0
- package/dist/logging/constructInfo.d.ts.map +1 -0
- package/dist/logging/constructInfo.js +15 -0
- package/dist/logging/constructInfo.js.map +1 -0
- package/dist/logging/logger.d.ts +24 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +70 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/mcp/debugger.d.ts +3 -0
- package/dist/mcp/debugger.d.ts.map +1 -0
- package/dist/mcp/debugger.js +37 -0
- package/dist/mcp/debugger.js.map +1 -0
- package/dist/mcp/getDocs.d.ts.map +1 -0
- package/dist/mcp/getDocs.js +56 -0
- package/dist/mcp/getDocs.js.map +1 -0
- package/dist/mcp/getGuide.d.ts +5 -0
- package/dist/mcp/getGuide.d.ts.map +1 -0
- package/dist/mcp/getGuide.js +17 -0
- package/dist/mcp/getGuide.js.map +1 -0
- package/dist/{tools → mcp/tools}/docs.d.ts +3 -0
- package/dist/mcp/tools/docs.d.ts.map +1 -0
- package/dist/mcp/tools/docs.js +86 -0
- package/dist/mcp/tools/docs.js.map +1 -0
- package/dist/mcp/tools/fileManager.d.ts +6 -0
- package/dist/mcp/tools/fileManager.d.ts.map +1 -0
- package/dist/mcp/tools/fileManager.js +233 -0
- package/dist/mcp/tools/fileManager.js.map +1 -0
- package/dist/mcp/tools/guides.d.ts +11 -0
- package/dist/mcp/tools/guides.d.ts.map +1 -0
- package/dist/mcp/tools/guides.js +130 -0
- package/dist/mcp/tools/guides.js.map +1 -0
- package/dist/mcp-sse.d.ts +3 -0
- package/dist/mcp-sse.d.ts.map +1 -0
- package/dist/mcp-sse.js +72 -0
- package/dist/mcp-sse.js.map +1 -0
- package/dist/mcp.d.ts +3 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +36 -0
- package/dist/mcp.js.map +1 -0
- package/dist/prompts/system.d.ts +4 -0
- package/dist/prompts/system.d.ts.map +1 -0
- package/dist/prompts/system.js +23 -0
- package/dist/prompts/system.js.map +1 -0
- package/dist/telemetry.d.ts +11 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +104 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/types/claude-sdk.d.ts +39 -0
- package/dist/types/claude-sdk.d.ts.map +1 -0
- package/dist/types/claude-sdk.js +5 -0
- package/dist/types/claude-sdk.js.map +1 -0
- package/dist/types/cli.d.ts +7 -0
- package/dist/types/cli.d.ts.map +1 -0
- package/dist/types/cli.js +5 -0
- package/dist/types/cli.js.map +1 -0
- package/dist/utils/agentManager.d.ts +22 -0
- package/dist/utils/agentManager.d.ts.map +1 -0
- package/dist/utils/agentManager.js +110 -0
- package/dist/utils/agentManager.js.map +1 -0
- package/dist/utils/claudeCode.d.ts +24 -0
- package/dist/utils/claudeCode.d.ts.map +1 -0
- package/dist/utils/claudeCode.js +167 -0
- package/dist/utils/claudeCode.js.map +1 -0
- package/dist/utils/dag/createDag.d.ts +24 -0
- package/dist/utils/dag/createDag.d.ts.map +1 -0
- package/dist/utils/dag/createDag.js +175 -0
- package/dist/utils/dag/createDag.js.map +1 -0
- package/dist/utils/debugLogger.d.ts +3 -0
- package/dist/utils/debugLogger.d.ts.map +1 -0
- package/dist/utils/debugLogger.js +36 -0
- package/dist/utils/debugLogger.js.map +1 -0
- package/dist/utils/fs/findConfigs.d.ts +11 -0
- package/dist/utils/fs/findConfigs.d.ts.map +1 -0
- package/dist/utils/fs/findConfigs.js +63 -0
- package/dist/utils/fs/findConfigs.js.map +1 -0
- package/dist/utils/fs/getFiles.d.ts +2 -0
- package/dist/utils/fs/getFiles.d.ts.map +1 -0
- package/dist/utils/fs/getFiles.js +8 -0
- package/dist/utils/fs/getFiles.js.map +1 -0
- package/dist/utils/fs/writeFiles.d.ts +2 -0
- package/dist/utils/fs/writeFiles.d.ts.map +1 -0
- package/dist/utils/fs/writeFiles.js +19 -0
- package/dist/utils/fs/writeFiles.js.map +1 -0
- package/dist/utils/getFiles.d.ts +30 -0
- package/dist/utils/getFiles.d.ts.map +1 -0
- package/dist/utils/getFiles.js +152 -0
- package/dist/utils/getFiles.js.map +1 -0
- package/dist/utils/getPaths.d.ts +1 -0
- package/dist/utils/getPaths.d.ts.map +1 -1
- package/dist/utils/getPaths.js +19 -3
- package/dist/utils/getPaths.js.map +1 -1
- package/dist/utils/mcpConfig.d.ts +10 -0
- package/dist/utils/mcpConfig.d.ts.map +1 -0
- package/dist/utils/mcpConfig.js +13 -0
- package/dist/utils/mcpConfig.js.map +1 -0
- package/dist/utils/shared.d.ts +2 -0
- package/dist/utils/shared.d.ts.map +1 -0
- package/dist/utils/shared.js +15 -0
- package/dist/utils/shared.js.map +1 -0
- package/dist/utils/validateConfig.d.ts +2 -0
- package/dist/utils/validateConfig.d.ts.map +1 -0
- package/dist/utils/validateConfig.js +12 -0
- package/dist/utils/validateConfig.js.map +1 -0
- package/guides/next/advanced/complicated-mapping-expressions.md +200 -0
- package/guides/next/advanced/interpolated-strings.md +162 -0
- package/guides/next/advanced/migrating.md +86 -0
- package/guides/next/advanced/ternary-operators.md +217 -0
- package/guides/next/advanced/var-outside-client-component.md +446 -0
- package/guides/next/advanced/var-outside-client-server-component.md +550 -0
- package/guides/next/advanced/var-outside-server-component.md +545 -0
- package/guides/next/basic/branches.md +282 -0
- package/guides/next/basic/client-side-components.md +214 -0
- package/guides/next/basic/jsx.md +259 -0
- package/guides/next/basic/locale-selector.md +5 -0
- package/guides/next/basic/server-side-components.md +164 -0
- package/guides/next/basic/setup.md +139 -0
- package/guides/next/basic/translating-html.md +36 -0
- package/guides/next/basic/variables.md +185 -0
- package/guides/next/important/functions.md +37 -0
- package/package.json +32 -13
- package/dist/resources/docs.d.ts +0 -4
- package/dist/resources/docs.d.ts.map +0 -1
- package/dist/resources/docs.js +0 -176
- package/dist/resources/docs.js.map +0 -1
- package/dist/tools/docs.d.ts.map +0 -1
- package/dist/tools/docs.js +0 -140
- package/dist/tools/docs.js.map +0 -1
- package/dist/utils/getDocs.d.ts.map +0 -1
- package/dist/utils/getDocs.js +0 -113
- package/dist/utils/getDocs.js.map +0 -1
- /package/dist/{utils → mcp}/getDocs.d.ts +0 -0
package/dist/utils/getPaths.js
CHANGED
|
@@ -1,7 +1,23 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="753d767d-b755-5567-ae1a-f45989169bc4")}catch(e){}}();
|
|
1
3
|
import path, { dirname } from 'node:path';
|
|
2
4
|
import { fileURLToPath } from 'node:url';
|
|
3
|
-
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
4
7
|
export function fromPackageRoot(relative) {
|
|
5
|
-
return path.resolve(__dirname,
|
|
8
|
+
return path.resolve(__dirname, `../../`, relative);
|
|
6
9
|
}
|
|
7
|
-
|
|
10
|
+
export function getLocadexVersion() {
|
|
11
|
+
const packageJsonPath = fromPackageRoot('package.json');
|
|
12
|
+
if (!fs.existsSync(packageJsonPath)) {
|
|
13
|
+
return 'unknown';
|
|
14
|
+
}
|
|
15
|
+
try {
|
|
16
|
+
return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')).version;
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
return 'unknown';
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=getPaths.js.map
|
|
23
|
+
//# debugId=753d767d-b755-5567-ae1a-f45989169bc4
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getPaths.js","sourceRoot":"","
|
|
1
|
+
{"version":3,"file":"getPaths.js","sources":["utils/getPaths.ts"],"sourceRoot":"/","sourcesContent":["import path, { dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport fs from 'node:fs';\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nexport function fromPackageRoot(relative: string) {\n return path.resolve(__dirname, `../../`, relative);\n}\n\nexport function getLocadexVersion(): string {\n const packageJsonPath = fromPackageRoot('package.json');\n\n if (!fs.existsSync(packageJsonPath)) {\n return 'unknown';\n }\n try {\n return JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')).version;\n } catch (error) {\n return 'unknown';\n }\n}\n"],"names":[],"mappings":";;AAAA,OAAO,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAE1D,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,eAAe,GAAG,eAAe,CAAC,cAAc,CAAC,CAAC;IAExD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACpC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IACtE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC","debug_id":"753d767d-b755-5567-ae1a-f45989169bc4"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpConfig.d.ts","sourceRoot":"/","sources":["utils/mcpConfig.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,SAAS;;;;;;;;CAQrB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7f14296e-5624-5b6f-8a78-0532dfec7bd1")}catch(e){}}();
|
|
3
|
+
export const mcpConfig = {
|
|
4
|
+
mcpServers: {
|
|
5
|
+
locadex: {
|
|
6
|
+
command: 'npx',
|
|
7
|
+
args: ['-y', 'locadex-mcp'],
|
|
8
|
+
env: {},
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=mcpConfig.js.map
|
|
13
|
+
//# debugId=7f14296e-5624-5b6f-8a78-0532dfec7bd1
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcpConfig.js","sources":["utils/mcpConfig.ts"],"sourceRoot":"/","sourcesContent":["export const mcpConfig = {\n mcpServers: {\n locadex: {\n command: 'npx',\n args: ['-y', 'locadex-mcp'],\n env: {},\n },\n },\n};\n"],"names":[],"mappings":";;AAAA,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,UAAU,EAAE;QACV,OAAO,EAAE;YACP,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC;YAC3B,GAAG,EAAE,EAAE;SACR;KACF;CACF,CAAC","debug_id":"7f14296e-5624-5b6f-8a78-0532dfec7bd1"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"/","sources":["utils/shared.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,UAUzB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="86a6bbba-8470-5393-a187-f9281d22e29b")}catch(e){}}();
|
|
3
|
+
export const EXCLUDED_DIRS = [
|
|
4
|
+
'./node_modules',
|
|
5
|
+
'./.git',
|
|
6
|
+
'./.locadex',
|
|
7
|
+
'./.next',
|
|
8
|
+
'./dist',
|
|
9
|
+
'./build',
|
|
10
|
+
'./out',
|
|
11
|
+
'./public',
|
|
12
|
+
'./static',
|
|
13
|
+
];
|
|
14
|
+
//# sourceMappingURL=shared.js.map
|
|
15
|
+
//# debugId=86a6bbba-8470-5393-a187-f9281d22e29b
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sources":["utils/shared.ts"],"sourceRoot":"/","sourcesContent":["export const EXCLUDED_DIRS = [\n './node_modules',\n './.git',\n './.locadex',\n './.next',\n './dist',\n './build',\n './out',\n './public',\n './static',\n];\n"],"names":[],"mappings":";;AAAA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,gBAAgB;IAChB,QAAQ;IACR,YAAY;IACZ,SAAS;IACT,QAAQ;IACR,SAAS;IACT,OAAO;IACP,UAAU;IACV,UAAU;CACX,CAAC","debug_id":"86a6bbba-8470-5393-a187-f9281d22e29b"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateConfig.d.ts","sourceRoot":"/","sources":["utils/validateConfig.ts"],"names":[],"mappings":"AAEA,wBAAgB,qBAAqB,SAQpC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="58e02bc2-5220-52f6-873e-12b0d3b04571")}catch(e){}}();
|
|
3
|
+
import { logger } from '../logging/logger.js';
|
|
4
|
+
export function validateInitialConfig() {
|
|
5
|
+
// Validate ANTHROPIC_API_KEY
|
|
6
|
+
if (!process.env.ANTHROPIC_API_KEY) {
|
|
7
|
+
logger.error('ANTHROPIC_API_KEY is not set! Please set it as an environment variable or in a .env | .env.local file.');
|
|
8
|
+
process.exit(1);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=validateConfig.js.map
|
|
12
|
+
//# debugId=58e02bc2-5220-52f6-873e-12b0d3b04571
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validateConfig.js","sources":["utils/validateConfig.ts"],"sourceRoot":"/","sourcesContent":["import { logger } from '../logging/logger.js';\n\nexport function validateInitialConfig() {\n // Validate ANTHROPIC_API_KEY\n if (!process.env.ANTHROPIC_API_KEY) {\n logger.error(\n 'ANTHROPIC_API_KEY is not set! Please set it as an environment variable or in a .env | .env.local file.'\n );\n process.exit(1);\n }\n}\n"],"names":[],"mappings":";;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,MAAM,UAAU,qBAAqB;IACnC,6BAA6B;IAC7B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;QACnC,MAAM,CAAC,KAAK,CACV,wGAAwG,CACzG,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC","debug_id":"58e02bc2-5220-52f6-873e-12b0d3b04571"}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# Internationalization Patterns for Dynamic Content
|
|
2
|
+
|
|
3
|
+
**Objective**: Implement internationalization for mapping expressions using `<T>`, `useGT()`/`getGT()`, and `useDict()`/`getDict()`.
|
|
4
|
+
|
|
5
|
+
## Core Principles
|
|
6
|
+
|
|
7
|
+
### `<T>` Component Usage
|
|
8
|
+
|
|
9
|
+
**Rule**: `<T>` components translate static JSX content only. Dynamic content requires alternative approaches.
|
|
10
|
+
|
|
11
|
+
**Valid pattern**:
|
|
12
|
+
```jsx
|
|
13
|
+
<T>
|
|
14
|
+
<div> Here's some translated text </div>
|
|
15
|
+
Here is some more translated text!
|
|
16
|
+
</T>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Invalid pattern** - `<T>` cannot process dynamic mapping:
|
|
20
|
+
```jsx
|
|
21
|
+
const MyComponent = () => {
|
|
22
|
+
const someList = [
|
|
23
|
+
<div>Hello Archie</div>,
|
|
24
|
+
<div>Hello Ernest</div>,
|
|
25
|
+
<div>Hello Brian</div>,
|
|
26
|
+
];
|
|
27
|
+
return <T>{someList.map((item) => item)}</T>; // INVALID
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Solution**: Apply `<T>` to individual static items, not the mapping operation:
|
|
32
|
+
```jsx
|
|
33
|
+
const MyComponent = () => {
|
|
34
|
+
const someList = [
|
|
35
|
+
<T><div>Hello Archie</div></T>,
|
|
36
|
+
<T><div>Hello Ernest</div></T>,
|
|
37
|
+
<T><div>Hello Brian</div></T>,
|
|
38
|
+
];
|
|
39
|
+
return <>{someList.map((item) => item)}</>;
|
|
40
|
+
};
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
**Key requirement**: Each `<T>` component must have direct access to static text content.
|
|
44
|
+
|
|
45
|
+
### String Translation Methods
|
|
46
|
+
|
|
47
|
+
#### `useGT()` and `getGT()` Pattern
|
|
48
|
+
|
|
49
|
+
**Implementation**: Translate individual strings within data structures before mapping:
|
|
50
|
+
|
|
51
|
+
```jsx
|
|
52
|
+
import { useGT } from "gt-next/client";
|
|
53
|
+
import { getGT } from "gt-next/server";
|
|
54
|
+
|
|
55
|
+
const MyComponent = () => {
|
|
56
|
+
// Client-side: const t = useGT();
|
|
57
|
+
// Server-side: const t = await getGT();
|
|
58
|
+
const t = useGT(); // or await getGT()
|
|
59
|
+
|
|
60
|
+
const someList = [
|
|
61
|
+
t('Hello Archie'),
|
|
62
|
+
t('Hello Ernest'),
|
|
63
|
+
t('Hello Brian'),
|
|
64
|
+
];
|
|
65
|
+
return <>{someList.map((item) => item)}</>;
|
|
66
|
+
};
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### `useDict()` and `getDict()` Pattern
|
|
70
|
+
|
|
71
|
+
**Note**: Dictionary approach separates content from implementation context. Use sparingly - only when content reuse across components justifies the separation.
|
|
72
|
+
|
|
73
|
+
**Dictionary structure**:
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"Greetings": {
|
|
77
|
+
"Archie": "Archie",
|
|
78
|
+
"Ernest": "Ernest",
|
|
79
|
+
"Brian": "Brian"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Implementation**:
|
|
85
|
+
```jsx
|
|
86
|
+
import { useDict } from "gt-next/client";
|
|
87
|
+
import { getDict } from "gt-next/server";
|
|
88
|
+
|
|
89
|
+
const MyComponent = () => {
|
|
90
|
+
// Client-side: const t = useDict();
|
|
91
|
+
// Server-side: const t = await getDict();
|
|
92
|
+
const t = useDict(); // or await getDict()
|
|
93
|
+
|
|
94
|
+
const someList = [
|
|
95
|
+
t('Greetings.Archie'),
|
|
96
|
+
t('Greetings.Ernest'),
|
|
97
|
+
t('Greetings.Brian'),
|
|
98
|
+
];
|
|
99
|
+
return <>{someList.map((item) => item)}</>;
|
|
100
|
+
};
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Complex Nested Object Translation
|
|
104
|
+
|
|
105
|
+
### Challenge: Multi-level Data Structures
|
|
106
|
+
|
|
107
|
+
**Scenario**: Nested objects with translatable content at multiple levels require systematic translation approach.
|
|
108
|
+
|
|
109
|
+
**Non-internationalized example**:
|
|
110
|
+
```jsx
|
|
111
|
+
const MyComponent = () => {
|
|
112
|
+
const users = {
|
|
113
|
+
archie: {
|
|
114
|
+
name: 'Archie',
|
|
115
|
+
role: 'Developer',
|
|
116
|
+
skills: ['JavaScript', 'React', 'TypeScript'],
|
|
117
|
+
},
|
|
118
|
+
ernest: {
|
|
119
|
+
name: 'Ernest',
|
|
120
|
+
role: 'Designer',
|
|
121
|
+
skills: ['UI/UX', 'Figma', 'Illustration'],
|
|
122
|
+
},
|
|
123
|
+
brian: {
|
|
124
|
+
name: 'Brian',
|
|
125
|
+
role: 'Product Manager',
|
|
126
|
+
skills: ['Strategy', 'Planning', 'Communication'],
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<div>
|
|
132
|
+
{Object.entries(users).map(([key, user]) => (
|
|
133
|
+
<div key={key}>
|
|
134
|
+
<h2>{user.name}</h2>
|
|
135
|
+
<p>Role: {user.role}</p>
|
|
136
|
+
<ul>
|
|
137
|
+
{user.skills.map((skill, index) => (
|
|
138
|
+
<li key={index}>{skill}</li>
|
|
139
|
+
))}
|
|
140
|
+
</ul>
|
|
141
|
+
</div>
|
|
142
|
+
))}
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Solution: Comprehensive Translation Strategy
|
|
149
|
+
|
|
150
|
+
**Requirements**:
|
|
151
|
+
- Translate role labels and skill names
|
|
152
|
+
- Handle string interpolation for template text
|
|
153
|
+
- Provide contextual information for ambiguous terms
|
|
154
|
+
|
|
155
|
+
**Implementation**:
|
|
156
|
+
```jsx
|
|
157
|
+
import { useGT } from 'gt-next/client';
|
|
158
|
+
|
|
159
|
+
const MyComponent = () => {
|
|
160
|
+
const t = useGT();
|
|
161
|
+
const users = {
|
|
162
|
+
archie: {
|
|
163
|
+
name: 'Archie',
|
|
164
|
+
role: t('Developer', { context: 'As in a software developer' }),
|
|
165
|
+
skills: [t('JavaScript'), t('React'), t('TypeScript')],
|
|
166
|
+
},
|
|
167
|
+
ernest: {
|
|
168
|
+
name: 'Ernest',
|
|
169
|
+
role: t('Designer', { context: 'As in a UI/UX designer' }),
|
|
170
|
+
skills: [t('UI/UX'), t('Figma'), t('Illustration')],
|
|
171
|
+
},
|
|
172
|
+
brian: {
|
|
173
|
+
name: 'Brian',
|
|
174
|
+
role: t('Product Manager'),
|
|
175
|
+
skills: [t('Strategy'), t('Planning'), t('Communication')],
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<div>
|
|
181
|
+
{Object.entries(users).map(([key, user]) => (
|
|
182
|
+
<div key={key}>
|
|
183
|
+
<h2>{user.name}</h2>
|
|
184
|
+
<p>{t('Role: {role}', { variables: { role: user.role } })}</p>
|
|
185
|
+
<ul>
|
|
186
|
+
{user.skills.map((skill, index) => (
|
|
187
|
+
<li key={index}>{skill}</li>
|
|
188
|
+
))}
|
|
189
|
+
</ul>
|
|
190
|
+
</div>
|
|
191
|
+
))}
|
|
192
|
+
</div>
|
|
193
|
+
);
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Key techniques**:
|
|
198
|
+
1. **Context provision**: `{ context: 'As in a software developer' }` for disambiguation
|
|
199
|
+
2. **Variable interpolation**: `t('Role: {role}', { variables: { role: user.role } })`
|
|
200
|
+
3. **Systematic translation**: Apply `t()` to all user-facing strings within data structure
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# String Interpolation Internationalization Patterns
|
|
2
|
+
|
|
3
|
+
**Objective**: Transform template literal strings with dynamic variables into translatable strings using `useGT()`/`getGT()` and `useDict()`/`getDict()`.
|
|
4
|
+
|
|
5
|
+
## Core Pattern: Variable Injection
|
|
6
|
+
|
|
7
|
+
### `useGT()`/`getGT()` Method
|
|
8
|
+
|
|
9
|
+
**Transform**: Template literals → Translatable strings with variable placeholders
|
|
10
|
+
|
|
11
|
+
**Non-internationalized pattern**:
|
|
12
|
+
|
|
13
|
+
```jsx
|
|
14
|
+
const MyComponent = ({ name, count }) => {
|
|
15
|
+
return <div>{`Welcome ${name}, you have ${count} items`}</div>;
|
|
16
|
+
};
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Internationalized implementation**:
|
|
20
|
+
|
|
21
|
+
**Option A** the `<T>` component (preferred for JSX/HTML):
|
|
22
|
+
|
|
23
|
+
```jsx
|
|
24
|
+
import { T } from 'gt-next';
|
|
25
|
+
|
|
26
|
+
const MyComponent = ({ name, count }) => {
|
|
27
|
+
return (
|
|
28
|
+
<div>
|
|
29
|
+
<T>
|
|
30
|
+
Welcome <Var>{name}</Var>, you have <Var>{count}</Var> items
|
|
31
|
+
</T>
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Option B** the `useGT()` hook:
|
|
38
|
+
|
|
39
|
+
```jsx
|
|
40
|
+
'use client';
|
|
41
|
+
import { useGT } from 'gt-next/client';
|
|
42
|
+
|
|
43
|
+
const MyComponent = ({ name, count }) => {
|
|
44
|
+
const t = useGT(); // Client-side
|
|
45
|
+
// const t = await getGT(); // Server-side
|
|
46
|
+
return (
|
|
47
|
+
<div>
|
|
48
|
+
{t('Welcome {name}, you have {count} items', {
|
|
49
|
+
variables: { name, count },
|
|
50
|
+
})}
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
};
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**Key requirements**:
|
|
57
|
+
|
|
58
|
+
- Replace `${variable}` syntax with `{variable}` placeholders
|
|
59
|
+
- Pass dynamic values via `variables` object
|
|
60
|
+
- Variable names must match placeholder names exactly
|
|
61
|
+
|
|
62
|
+
### `useDict()`/`getDict()` Method
|
|
63
|
+
|
|
64
|
+
**Option C**: Template literals → Dictionary keys with variable placeholders
|
|
65
|
+
|
|
66
|
+
**Non-internationalized pattern**:
|
|
67
|
+
|
|
68
|
+
```jsx
|
|
69
|
+
const MyComponent = ({ username, role }) => {
|
|
70
|
+
return <div>{`User ${username} has the role of ${role}`}</div>;
|
|
71
|
+
};
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Dictionary structure**:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"Users": {
|
|
79
|
+
"Profile": "User {username} has the role of {role}"
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Implementation**:
|
|
85
|
+
|
|
86
|
+
```jsx
|
|
87
|
+
'use client';
|
|
88
|
+
import { useDict } from 'gt-next/client';
|
|
89
|
+
const MyComponent = ({ username, role }) => {
|
|
90
|
+
const t = useDict(); // Client-side
|
|
91
|
+
// const t = await getDict(); // Server-side
|
|
92
|
+
return (
|
|
93
|
+
<div>
|
|
94
|
+
{t('Users.Profile', {
|
|
95
|
+
variables: { username, role },
|
|
96
|
+
})}
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
};
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Advanced Patterns
|
|
103
|
+
|
|
104
|
+
### Multi-Variable Interpolation
|
|
105
|
+
|
|
106
|
+
**Scenario**: Multiple dynamic values in a single translatable string
|
|
107
|
+
|
|
108
|
+
**Implementation**:
|
|
109
|
+
|
|
110
|
+
```jsx
|
|
111
|
+
'use client';
|
|
112
|
+
import { useGT } from 'gt-next/client';
|
|
113
|
+
const MyComponent = ({ firstName, lastName, age, city }) => {
|
|
114
|
+
const t = useGT(); // Client-side
|
|
115
|
+
// const t = await getGT(); // Server-side
|
|
116
|
+
return (
|
|
117
|
+
<div>
|
|
118
|
+
{t('{firstName} {lastName} is {age} years old and lives in {city}', {
|
|
119
|
+
variables: { firstName, lastName, age, city },
|
|
120
|
+
})}
|
|
121
|
+
</div>
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Requirements**: All placeholder names must have corresponding entries in `variables` object.
|
|
127
|
+
|
|
128
|
+
### Object Property Extraction
|
|
129
|
+
|
|
130
|
+
**Scenario**: Extract values from nested objects for interpolation
|
|
131
|
+
|
|
132
|
+
**Dictionary definition**:
|
|
133
|
+
|
|
134
|
+
```json
|
|
135
|
+
{
|
|
136
|
+
"Users": {
|
|
137
|
+
"Details": "{name} works as a {role} in the {department} department"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Implementation**:
|
|
143
|
+
|
|
144
|
+
```jsx
|
|
145
|
+
const MyComponent = ({ user }) => {
|
|
146
|
+
const t = useDict(); // Client-side
|
|
147
|
+
// const t = await getDict(); // Server-side
|
|
148
|
+
return (
|
|
149
|
+
<div>
|
|
150
|
+
{t('Users.Details', {
|
|
151
|
+
variables: {
|
|
152
|
+
name: user.name,
|
|
153
|
+
role: user.role,
|
|
154
|
+
department: user.department,
|
|
155
|
+
},
|
|
156
|
+
})}
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
};
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
**Pattern**: Explicitly map object properties to named variables for clear placeholder relationships.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Migration Patterns for Existing i18n Projects
|
|
2
|
+
|
|
3
|
+
**Objective**: Transform existing i18n implementations to `gt-next` using systematic migration strategies.
|
|
4
|
+
|
|
5
|
+
## Core Migration Principles
|
|
6
|
+
|
|
7
|
+
### Library Replacement Requirements
|
|
8
|
+
|
|
9
|
+
- Replace existing i18n library hooks/functions with `gt-next` equivalents
|
|
10
|
+
- Transform string keys to inline content or maintain dictionary structure
|
|
11
|
+
- Preserve existing translation content during transition
|
|
12
|
+
|
|
13
|
+
## Prerequisites
|
|
14
|
+
|
|
15
|
+
The project should be setup with `gt-next`. See the guide on setting up gt-next in a Next.js project.
|
|
16
|
+
|
|
17
|
+
## Migration Strategy Implementation
|
|
18
|
+
|
|
19
|
+
**Objective**: Full transformation from existing i18n library to `gt-next` with string key elimination.
|
|
20
|
+
|
|
21
|
+
**Hook replacement pattern**:
|
|
22
|
+
|
|
23
|
+
- Replace old i18n library hooks/functions with `gt-next` equivalents
|
|
24
|
+
- Transform string keys → inline content
|
|
25
|
+
|
|
26
|
+
**Implementation transformation**:
|
|
27
|
+
|
|
28
|
+
**Legacy pattern**:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"hello": {
|
|
33
|
+
"description": "Hello, world!"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
export default function MyComponent() {
|
|
40
|
+
const { t } = useTranslation();
|
|
41
|
+
return <div>{t('hello.description')}</div>;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Migrated implementations**:
|
|
46
|
+
|
|
47
|
+
**Option A - Component-based** (preferred):
|
|
48
|
+
|
|
49
|
+
```tsx
|
|
50
|
+
export default function MyComponent() {
|
|
51
|
+
return (
|
|
52
|
+
<T>
|
|
53
|
+
<div>Hello, world!</div>
|
|
54
|
+
</T>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Option B - Hook-based**:
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
'use client'; // Always add 'use client' when working with the useGT() hook
|
|
63
|
+
import { useGT } from 'gt-next/client';
|
|
64
|
+
export default function MyComponent() {
|
|
65
|
+
const t = useGT();
|
|
66
|
+
return <div>{t('Hello, world!')}</div>;
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Requirements**: Systematic replacement of all legacy i18n library instances.
|
|
71
|
+
|
|
72
|
+
## Migration Implementation Guidelines
|
|
73
|
+
|
|
74
|
+
### Primary Pattern Preference
|
|
75
|
+
|
|
76
|
+
**Rule**: Prioritize `useGT()` hook, `getGT()` function, and `<T>` component usage whenever possible.
|
|
77
|
+
|
|
78
|
+
**Benefits**:
|
|
79
|
+
|
|
80
|
+
- Enhanced content editability
|
|
81
|
+
- Improved code readability
|
|
82
|
+
- Contextual content management
|
|
83
|
+
|
|
84
|
+
### Dictionary Hook Usage
|
|
85
|
+
|
|
86
|
+
**Rule**: Only apply `useDict()` and `getDict()` during migration when necessary.
|