@mdbase-dev/i18n 0.0.0-stage → 0.1.0-beta.147
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/LICENSE +21 -0
- package/README.md +299 -2
- package/dist/codemirror/de.d.ts +3 -0
- package/dist/codemirror/de.js +33 -0
- package/dist/codemirror/en.d.ts +3 -0
- package/dist/codemirror/en.js +33 -0
- package/dist/codemirror/es.d.ts +3 -0
- package/dist/codemirror/es.js +33 -0
- package/dist/codemirror/fr.d.ts +3 -0
- package/dist/codemirror/fr.js +33 -0
- package/dist/codemirror/it.d.ts +3 -0
- package/dist/codemirror/it.js +33 -0
- package/dist/codemirror/ja.d.ts +3 -0
- package/dist/codemirror/ja.js +33 -0
- package/dist/codemirror/ko.d.ts +3 -0
- package/dist/codemirror/ko.js +33 -0
- package/dist/codemirror/pt.d.ts +3 -0
- package/dist/codemirror/pt.js +33 -0
- package/dist/codemirror/ru.d.ts +3 -0
- package/dist/codemirror/ru.js +33 -0
- package/dist/codemirror/zh.d.ts +3 -0
- package/dist/codemirror/zh.js +33 -0
- package/dist/codemirror.d.ts +8 -0
- package/dist/codemirror.js +17 -0
- package/dist/react.d.ts +13 -0
- package/dist/react.js +28 -0
- package/dist/runtime.d.ts +42 -0
- package/dist/runtime.js +112 -0
- package/package.json +75 -3
- package/scripts/bin.mjs +7 -0
- package/scripts/catalogues.d.mts +2 -0
- package/scripts/catalogues.mjs +25 -0
- package/scripts/checks.mjs +114 -0
- package/scripts/cli.mjs +108 -0
- package/scripts/config.d.mts +6 -0
- package/scripts/config.mjs +13 -0
- package/scripts/source.mjs +297 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mdbase connect contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,300 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @mdbase-dev/i18n
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Shared, locally authored Lingui 6.9 tooling and React runtime. No remote service,
|
|
4
|
+
AI provider, translation network endpoint or application data model.
|
|
5
|
+
English starts synchronously; an app's own bundler serves lazy non-English JSON.
|
|
6
|
+
Supported locales: `en fr de es ja ko pt ru zh it`. `pt` is Brazilian Portuguese
|
|
7
|
+
(the TaskNotes plugin explicitly labels it Português (Brasil)); `zh` is Simplified Chinese.
|
|
8
|
+
Mechanical checks do not certify linguistic quality or native-device acceptance.
|
|
9
|
+
|
|
10
|
+
## Adopt
|
|
11
|
+
|
|
12
|
+
Install this package, `@lingui/core@6.9.0`, `@lingui/react@6.9.0` and React 19.
|
|
13
|
+
For Vite, also install `@lingui/vite-plugin@6.9.0` and configure the Lingui plugin
|
|
14
|
+
as in the Lingui Vite documentation: macros must be transformed, not shipped as calls.
|
|
15
|
+
A React Babel pipeline can instead use `@lingui/babel-plugin-lingui-macro@6.9.0`.
|
|
16
|
+
This kit does not replace the application's build configuration.
|
|
17
|
+
|
|
18
|
+
`lingui.config.mjs` (or `.ts`):
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import { i18nConfig } from "@mdbase-dev/i18n/config";
|
|
22
|
+
export default i18nConfig({
|
|
23
|
+
include: ["<rootDir>/src"],
|
|
24
|
+
exclude: ["**/*.test.*", "**/*.spec.*"],
|
|
25
|
+
path: "<rootDir>/src/i18n/locales/{locale}/messages",
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
`package.json` scripts:
|
|
30
|
+
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"i18n:extract": "mdbase-i18n extract",
|
|
34
|
+
"i18n:compile": "mdbase-i18n compile",
|
|
35
|
+
"i18n:check": "mdbase-i18n check"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Mark visible copy with Lingui macros. Let IDs be generated from English + semantic
|
|
40
|
+
context; never invent explicit IDs. Add context for ambiguous short action/state
|
|
41
|
+
labels. Don't translate user data, paths, product names or protocol identifiers.
|
|
42
|
+
Don't translate eagerly at module scope, nest `t` inside another `t` interpolation,
|
|
43
|
+
or use translations in comparisons, lookups or CSS identifiers.
|
|
44
|
+
|
|
45
|
+
Run extract, author all nine target PO files, then check. PO is the authoring source.
|
|
46
|
+
The kit's `compile` and `check` commands prune obsolete entries from configured PO
|
|
47
|
+
files before Lingui compilation or fallback resolution. Compiled JSON contains only
|
|
48
|
+
active messages; still-active translations are preserved. Package builds must use
|
|
49
|
+
`mdbase-i18n compile`, not direct `lingui compile`, which includes obsolete entries
|
|
50
|
+
in Lingui 6.9. The Connect apps/shared UI use this same kit compile boundary.
|
|
51
|
+
The check runs extraction sync, raw-PO completeness **before fallback**, generated IDs,
|
|
52
|
+
ICU argument/type, select/exact numeric cases, offset, pound and numeric React-tag
|
|
53
|
+
contracts, strict JSON compilation and the structural source guard. Plural categories
|
|
54
|
+
follow the target locale's grammar (Japanese/Chinese need not have English `one`;
|
|
55
|
+
Russian needs its own categories). Translated plural/ordinal messages must cover
|
|
56
|
+
categories selected by `Intl.PluralRules` for integer counts **0..999**, with plural
|
|
57
|
+
offsets applied. PO messages contain no reliable call-site numeric domain, so the
|
|
58
|
+
check does not infer fractional counts. `other` is always required; unknown categories
|
|
59
|
+
fail. `pt` uses `pt-BR`. Source exact numeric arms must remain; extra `=N` arms are
|
|
60
|
+
allowed. Exact arms satisfy a category only if they cover every integer in the domain
|
|
61
|
+
that selects it (de/es `one`: `=1`; fr/pt `one`: both `=0` and `=1`). Exact arms match
|
|
62
|
+
original counts, before subtracting an offset. Missing CLDR categories unreachable
|
|
63
|
+
in that domain (e.g. fr/es/pt/it million-only `many`) produce **informational stdout
|
|
64
|
+
notes**, not warnings or errors. They remain valid optional arms. Missing, fuzzy and whole-message
|
|
65
|
+
English-placeholder translations fail. Plural/ordinal/select branches byte-identical
|
|
66
|
+
to the corresponding English branch (or English `other` for added categories) warn
|
|
67
|
+
when the branch contains literal letters. Warnings include locale, generated ID and
|
|
68
|
+
selector path; the same reviewed `allowIdentical` IDs suppress them, but never waive
|
|
69
|
+
ICU contracts. Numeric/punctuation-only branches and argument names do not warn.
|
|
70
|
+
Nothing in CI authors translations.
|
|
71
|
+
|
|
72
|
+
Reviewed identical terms/proper nouns require explicit per-locale generated-ID
|
|
73
|
+
allowlisting. Optional `i18n-policy.json`:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"allowIdentical": { "fr": ["generated-id-for-a-reviewed-proper-noun"] },
|
|
78
|
+
"source": {
|
|
79
|
+
"include": ["src/components", "src/screens"],
|
|
80
|
+
"exclude": ["**/generated/**"],
|
|
81
|
+
"brands": ["YourProduct"]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Includes are directories, relative to the config root (not glob expressions).
|
|
87
|
+
Excludes are glob patterns. The guard defaults to catalogue includes/excludes and
|
|
88
|
+
skips tests, locale data and node_modules. It catches visible JSX/attribute strings
|
|
89
|
+
and local React state rendered as copy (including notices passed to its setter),
|
|
90
|
+
plus unsafe translation placement, not arbitrary UI copy in every non-React dependency;
|
|
91
|
+
source review remains necessary. Object state is tracked by rendered member path:
|
|
92
|
+
`notice.text` checks only `text` in initializers and setter updates, not sibling
|
|
93
|
+
CSS/control-flow discriminators. Nested and literal-computed member paths work too.
|
|
94
|
+
State used only as a truthiness gate, enum/lookup key, input value or opaque component
|
|
95
|
+
prop spread is not visible copy; types are never copy. Explicit-instance core macros, plural/select helpers inside `t`
|
|
96
|
+
ICU templates and class instance-field translations are supported; static fields and
|
|
97
|
+
module-level translations remain eager and fail. Keep exclusions narrow and justified.
|
|
98
|
+
`mdbase-i18n source` runs only the guard; `--config path` selects a Lingui config.
|
|
99
|
+
|
|
100
|
+
## Runtime and picker
|
|
101
|
+
|
|
102
|
+
Create one runtime **outside React rendering**. Apps already using core `t` macros
|
|
103
|
+
should pass `i18n` from `@lingui/core` as the optional `i18n` property. The provider
|
|
104
|
+
and non-React helpers then share that singleton. Omit it for an isolated instance.
|
|
105
|
+
Only one runtime may own a supplied instance. English is a static import;
|
|
106
|
+
enumerate imports so Vite/other bundlers can make local-deployment chunks:
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
import english from "./i18n/locales/en/messages.json";
|
|
110
|
+
import { createI18nRuntime } from "@mdbase-dev/i18n";
|
|
111
|
+
import { LocaleProvider, LanguagePicker } from "@mdbase-dev/i18n/react";
|
|
112
|
+
|
|
113
|
+
const loaders = {
|
|
114
|
+
fr: () => import("./i18n/locales/fr/messages.json"),
|
|
115
|
+
de: () => import("./i18n/locales/de/messages.json"),
|
|
116
|
+
es: () => import("./i18n/locales/es/messages.json"),
|
|
117
|
+
ja: () => import("./i18n/locales/ja/messages.json"),
|
|
118
|
+
ko: () => import("./i18n/locales/ko/messages.json"),
|
|
119
|
+
pt: () => import("./i18n/locales/pt/messages.json"),
|
|
120
|
+
ru: () => import("./i18n/locales/ru/messages.json"),
|
|
121
|
+
zh: () => import("./i18n/locales/zh/messages.json"),
|
|
122
|
+
it: () => import("./i18n/locales/it/messages.json"),
|
|
123
|
+
};
|
|
124
|
+
export const runtime = createI18nRuntime({
|
|
125
|
+
english,
|
|
126
|
+
loadLocale: async (locale) => (await loaders[locale]()).default,
|
|
127
|
+
// Adapter is app-owned. Catch unavailable browser storage here if best-effort.
|
|
128
|
+
storage: {
|
|
129
|
+
getLocale: () => localStorage.getItem("my-app:locale"),
|
|
130
|
+
setLocale: (locale) => localStorage.setItem("my-app:locale", locale),
|
|
131
|
+
},
|
|
132
|
+
// Optional native OS locale list; defaults to navigator.languages.
|
|
133
|
+
// preferences: ["fr-CA"],
|
|
134
|
+
});
|
|
135
|
+
// Wrap the root once; portals retain real Lingui context.
|
|
136
|
+
<LocaleProvider runtime={runtime} onError={showLanguageLoadError}>
|
|
137
|
+
<App />
|
|
138
|
+
</LocaleProvider>;
|
|
139
|
+
// Inside a translated component:
|
|
140
|
+
<LanguagePicker label={t`Language`} onError={showLanguageLoadError} />;
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The native, unstyled select has an accessible name, endonym options and a loading/
|
|
144
|
+
disabled state. Apply your existing select class. Apps own translated error notices.
|
|
145
|
+
`initialize()` is idempotent and provider-triggered after the immediate English render.
|
|
146
|
+
Explicit saved choice wins; otherwise the first supported browser/OS base language
|
|
147
|
+
wins, then English. An explicit user selection persists after successful activation.
|
|
148
|
+
Unsupported persisted choices are ignored. Failure retains the working catalogue
|
|
149
|
+
and previous choice; late loads can't replace newer selections. Storage adapter
|
|
150
|
+
errors are reported rather than silently swallowed. `html.lang` and `dir=ltr` track
|
|
151
|
+
activation. English startup does not mean collection access works offline.
|
|
152
|
+
|
|
153
|
+
Use `useLingui()` in components and `runtime.i18n` outside React. If you inject
|
|
154
|
+
Lingui's global singleton, existing core macros work unchanged. With an isolated
|
|
155
|
+
runtime instead, use
|
|
156
|
+
`const { t } = useLingui()` from `@lingui/react/macro`, or core macros with the
|
|
157
|
+
runtime explicitly supplied, `t(runtime.i18n)` / `runtime.i18n._(msg`...`)`.
|
|
158
|
+
Do not mix separate translator instances.
|
|
159
|
+
|
|
160
|
+
`formatters(runtime.i18n.locale)` provides Intl-backed `date`, `number` and
|
|
161
|
+
`relativeTime` functions. Call during rendering so a language change updates display.
|
|
162
|
+
These are display-only; never use them for persisted timestamps or enum values.
|
|
163
|
+
Portuguese Intl formatting uses `pt-BR`, Chinese `zh-CN`. Italian uses `it`.
|
|
164
|
+
Italian cardinal plurals require `one`/`other` (`many` is optional for millions);
|
|
165
|
+
ordinals require `many`/`other` (8, 11, 80 and 800 select `many`).
|
|
166
|
+
Language picker options use fixed endonyms from `localeNames`, not PO messages;
|
|
167
|
+
Italian is displayed as `Italiano`.
|
|
168
|
+
|
|
169
|
+
## Library catalogues (shared UI packages)
|
|
170
|
+
|
|
171
|
+
A library owns its source scope and ten PO catalogues; **do not extract its source
|
|
172
|
+
again into every app catalogue**. It does not create an i18n instance or provider.
|
|
173
|
+
React library components use `useLingui`/`Trans` from the parent app context.
|
|
174
|
+
Source macro calls must be transformed by the library build before publication:
|
|
175
|
+
plain `tsc` does not compile Lingui macros. Ship compiled JS and ICU JSON, never
|
|
176
|
+
untransformed macros requiring the consumer to process node_modules.
|
|
177
|
+
|
|
178
|
+
Export a `CatalogueSource` from a small `/i18n` entry point. For example
|
|
179
|
+
`packages/app-ui/src/i18n.ts`:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
import type { CatalogueSource } from "@mdbase-dev/i18n";
|
|
183
|
+
import english from "./locales/en/messages.json" with { type: "json" };
|
|
184
|
+
const loaders = {
|
|
185
|
+
fr: () => import("./locales/fr/messages.json", { with: { type: "json" } }),
|
|
186
|
+
de: () => import("./locales/de/messages.json", { with: { type: "json" } }),
|
|
187
|
+
es: () => import("./locales/es/messages.json", { with: { type: "json" } }),
|
|
188
|
+
ja: () => import("./locales/ja/messages.json", { with: { type: "json" } }),
|
|
189
|
+
ko: () => import("./locales/ko/messages.json", { with: { type: "json" } }),
|
|
190
|
+
pt: () => import("./locales/pt/messages.json", { with: { type: "json" } }),
|
|
191
|
+
ru: () => import("./locales/ru/messages.json", { with: { type: "json" } }),
|
|
192
|
+
zh: () => import("./locales/zh/messages.json", { with: { type: "json" } }),
|
|
193
|
+
it: () => import("./locales/it/messages.json", { with: { type: "json" } }),
|
|
194
|
+
};
|
|
195
|
+
export const uiCatalogues: CatalogueSource = {
|
|
196
|
+
english,
|
|
197
|
+
loadLocale: async (locale) => (await loaders[locale]()).default,
|
|
198
|
+
};
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The library's config includes only its own `src` and uses
|
|
202
|
+
`path: "<rootDir>/src/locales/{locale}/messages"`. Run its own `mdbase-i18n check`
|
|
203
|
+
for all ten locales. Copy **all ten JSON files** into `dist/locales/{locale}`
|
|
204
|
+
and preserve the literal imports above during the library build, so the application
|
|
205
|
+
bundler can split its own deployment's target-language chunks. Include these files
|
|
206
|
+
in the packed tarball and smoke-test the packed `/i18n` entry. Add a package export:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
{
|
|
210
|
+
"exports": {
|
|
211
|
+
"./i18n": { "types": "./dist/i18n.d.ts", "import": "./dist/i18n.js" }
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Keep React, `@lingui/core@6.9.0`, `@lingui/react@6.9.0` and this kit as
|
|
217
|
+
peer dependencies (workspace development dependencies in Connect) rather than
|
|
218
|
+
bundling nested translator copies. The library's runtime imports are erased for
|
|
219
|
+
the kit type above, but the public declaration references its type.
|
|
220
|
+
|
|
221
|
+
At the application root:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import { uiCatalogues } from "@mdbase-dev/ui/i18n";
|
|
225
|
+
const runtime = createI18nRuntime({
|
|
226
|
+
english: appEnglish,
|
|
227
|
+
loadLocale: loadAppLocale,
|
|
228
|
+
libraries: [uiCatalogues],
|
|
229
|
+
// i18n: globalI18n, storage: appStorage,
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
English is merged synchronously. On a switch, the runtime loads the app and every
|
|
234
|
+
library catalogue concurrently, validates/merges them, then performs **one**
|
|
235
|
+
activation. A failed chunk or conflicting translation retains the current language
|
|
236
|
+
and stored choice; no mixed-language intermediate state is activated. Previously
|
|
237
|
+
activated locales are reused. `mergeCatalogues([...])` is also exported for
|
|
238
|
+
standalone deterministic composition: output keys and nested object keys are sorted,
|
|
239
|
+
identical generated-ID values become one entry, and different values for the same
|
|
240
|
+
ID throw instead of silently overriding one another. If two concepts really need
|
|
241
|
+
different wording, give them different semantic source contexts; otherwise align
|
|
242
|
+
their translations. No library prefixes, app-side ID rewriting or duplicate messages.
|
|
243
|
+
|
|
244
|
+
Catch these collisions before runtime by including each library's compiled JSON path
|
|
245
|
+
in the application's check command (quote `{locale}`; all ten locales are checked):
|
|
246
|
+
|
|
247
|
+
```sh
|
|
248
|
+
mdbase-i18n check --compose 'node_modules/@mdbase-dev/ui/dist/locales/{locale}/messages.json'
|
|
249
|
+
# Multiple libraries: append more path templates, or repeat --compose.
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Paths are filesystem paths relative to the Lingui config root, not JS `CatalogueSource`
|
|
253
|
+
modules; include every library passed to `libraries` at runtime. Libraries must be
|
|
254
|
+
compiled/built first. The check compiles app catalogues, then uses the runtime's exact
|
|
255
|
+
compiled-value comparison across all app scopes and supplied libraries. Identical
|
|
256
|
+
values deduplicate, including ICU objects with different key order. Failure reports
|
|
257
|
+
**every conflicting ID, locale and pair of compiled values**; missing library JSON
|
|
258
|
+
fails too. No last-wins overrides or collision allowlist.
|
|
259
|
+
|
|
260
|
+
For this monorepo: public `packages/app-ui` (`@mdbase-dev/ui`) ships its own
|
|
261
|
+
catalogues and `/i18n` export for Writer, Reader and TaskNotes. Private
|
|
262
|
+
`packages/ui` (`@mdbase/connect-ui`) ships a separate `/i18n` export for
|
|
263
|
+
Connect applications, which pass **both** sources when they use both packages.
|
|
264
|
+
Do not make the private package public or fold either library's UI into Portal's
|
|
265
|
+
application PO scope. A shared library's incomplete locale blocks that consuming
|
|
266
|
+
app's release; English fallback must not hide missing authored library messages.
|
|
267
|
+
|
|
268
|
+
## CodeMirror
|
|
269
|
+
|
|
270
|
+
`@mdbase-dev/i18n/codemirror` shares the fixed lookup keys from CodeMirror 6's
|
|
271
|
+
view, search, autocomplete, language, commands and lint packages. Keep the literal
|
|
272
|
+
`$` tokens: CodeMirror substitutes line/count values after lookup.
|
|
273
|
+
Start with synchronous `englishCodeMirrorPhrases`. On activation, await
|
|
274
|
+
`loadCodeMirrorPhrases(locale)` and reconfigure `EditorState.phrases` through a
|
|
275
|
+
compartment. Each non-English phrase dictionary is its own lazy local-deployment
|
|
276
|
+
chunk. Do not translate the document or serialized editor state.
|
|
277
|
+
|
|
278
|
+
## CI, packing and vendoring
|
|
279
|
+
|
|
280
|
+
Run `pnpm i18n:check` in CI before build/tests. If compiled JSON is committed,
|
|
281
|
+
also `git diff --exit-code -- path/to/locales` after the check. Check doesn't need
|
|
282
|
+
network or an AI key; only dependency installation does. There is no delivery
|
|
283
|
+
manifest or pack-fetch protocol in this package.
|
|
284
|
+
|
|
285
|
+
Kit verification: `pnpm --filter @mdbase-dev/i18n verify`.
|
|
286
|
+
`pnpm --filter @mdbase-dev/i18n test:packed` repeats the packed-consumer check:
|
|
287
|
+
real extraction, all ten authored catalogues, strict compile and source checks
|
|
288
|
+
through an npm-style `node_modules/.bin` symlink, including rejection of a broken
|
|
289
|
+
catalogue. The public bin always invokes the CLI; consumers should use the bare
|
|
290
|
+
`mdbase-i18n` commands above and remove temporary exported-main adapter launchers.
|
|
291
|
+
Build before `pnpm --filter @mdbase-dev/i18n pack --pack-destination <directory>`.
|
|
292
|
+
The tarball includes built ESM/types plus its self-contained CLI/scripts; no workspace
|
|
293
|
+
dependency or source checkout is required. React and Lingui core/react are peers.
|
|
294
|
+
|
|
295
|
+
Before npm publication, external products must copy the coordinated tarball into
|
|
296
|
+
`vendor/mdbase-dev-i18n-<version>-<shortsha>.tgz` and use a relative `file:` dependency,
|
|
297
|
+
then commit their lockfile. Record the exact kit SHA in the PR. **Swap the vendored
|
|
298
|
+
dependency for the published npm version at merge time**, once that Connect release
|
|
299
|
+
is available. Never depend on another worktree's node_modules or absolute paths.
|
|
300
|
+
This branch prepares release-cohort inclusion; it does not publish or deploy.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Fixed CodeMirror lookup keys; preserve literal $ substitution tokens. */
|
|
2
|
+
const phrases = {
|
|
3
|
+
"Control character": "Steuerzeichen",
|
|
4
|
+
"Selection deleted": "Auswahl gelöscht",
|
|
5
|
+
"Completions": "Vervollständigungen",
|
|
6
|
+
"Folded lines": "Eingeklappte Zeilen",
|
|
7
|
+
"Unfolded lines": "Ausgeklappte Zeilen",
|
|
8
|
+
"Fold line": "Zeile einklappen",
|
|
9
|
+
"Unfold line": "Zeile ausklappen",
|
|
10
|
+
"folded code": "Eingeklappter Code",
|
|
11
|
+
"unfold": "Ausklappen",
|
|
12
|
+
"to": "bis",
|
|
13
|
+
"Go to line": "Gehe zu Zeile",
|
|
14
|
+
"go": "Los",
|
|
15
|
+
"Find": "Suchen",
|
|
16
|
+
"Replace": "Ersetzen",
|
|
17
|
+
"next": "Weiter",
|
|
18
|
+
"previous": "Zurück",
|
|
19
|
+
"all": "Alle",
|
|
20
|
+
"match case": "Groß-/Kleinschreibung beachten",
|
|
21
|
+
"regexp": "Regulärer Ausdruck",
|
|
22
|
+
"by word": "Ganze Wörter",
|
|
23
|
+
"replace": "Ersetzen",
|
|
24
|
+
"replace all": "Alle ersetzen",
|
|
25
|
+
"close": "Schließen",
|
|
26
|
+
"current match": "Aktueller Treffer",
|
|
27
|
+
"on line": "in Zeile",
|
|
28
|
+
"replaced match on line $": "Treffer in Zeile $ ersetzt",
|
|
29
|
+
"replaced $ matches": "$ Treffer ersetzt",
|
|
30
|
+
"Diagnostics": "Diagnosen",
|
|
31
|
+
"No diagnostics": "Keine Diagnosen"
|
|
32
|
+
};
|
|
33
|
+
export default phrases;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Fixed CodeMirror lookup keys; preserve literal $ substitution tokens. */
|
|
2
|
+
const phrases = {
|
|
3
|
+
"Control character": "Control character",
|
|
4
|
+
"Selection deleted": "Selection deleted",
|
|
5
|
+
"Completions": "Completions",
|
|
6
|
+
"Folded lines": "Folded lines",
|
|
7
|
+
"Unfolded lines": "Unfolded lines",
|
|
8
|
+
"Fold line": "Fold line",
|
|
9
|
+
"Unfold line": "Unfold line",
|
|
10
|
+
"folded code": "Folded code",
|
|
11
|
+
"unfold": "Unfold",
|
|
12
|
+
"to": "to",
|
|
13
|
+
"Go to line": "Go to line",
|
|
14
|
+
"go": "Go",
|
|
15
|
+
"Find": "Find",
|
|
16
|
+
"Replace": "Replace",
|
|
17
|
+
"next": "Next",
|
|
18
|
+
"previous": "Previous",
|
|
19
|
+
"all": "All",
|
|
20
|
+
"match case": "Match case",
|
|
21
|
+
"regexp": "Regular expression",
|
|
22
|
+
"by word": "Whole words",
|
|
23
|
+
"replace": "Replace",
|
|
24
|
+
"replace all": "Replace all",
|
|
25
|
+
"close": "Close",
|
|
26
|
+
"current match": "Current match",
|
|
27
|
+
"on line": "on line",
|
|
28
|
+
"replaced match on line $": "Replaced match on line $",
|
|
29
|
+
"replaced $ matches": "Replaced $ matches",
|
|
30
|
+
"Diagnostics": "Diagnostics",
|
|
31
|
+
"No diagnostics": "No diagnostics"
|
|
32
|
+
};
|
|
33
|
+
export default phrases;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Fixed CodeMirror lookup keys; preserve literal $ substitution tokens. */
|
|
2
|
+
const phrases = {
|
|
3
|
+
"Control character": "Carácter de control",
|
|
4
|
+
"Selection deleted": "Selección eliminada",
|
|
5
|
+
"Completions": "Sugerencias",
|
|
6
|
+
"Folded lines": "Líneas plegadas",
|
|
7
|
+
"Unfolded lines": "Líneas desplegadas",
|
|
8
|
+
"Fold line": "Plegar línea",
|
|
9
|
+
"Unfold line": "Desplegar línea",
|
|
10
|
+
"folded code": "Código plegado",
|
|
11
|
+
"unfold": "Desplegar",
|
|
12
|
+
"to": "a",
|
|
13
|
+
"Go to line": "Ir a la línea",
|
|
14
|
+
"go": "Ir",
|
|
15
|
+
"Find": "Buscar",
|
|
16
|
+
"Replace": "Reemplazar",
|
|
17
|
+
"next": "Siguiente",
|
|
18
|
+
"previous": "Anterior",
|
|
19
|
+
"all": "Todo",
|
|
20
|
+
"match case": "Distinguir mayúsculas",
|
|
21
|
+
"regexp": "Expresión regular",
|
|
22
|
+
"by word": "Palabras completas",
|
|
23
|
+
"replace": "Reemplazar",
|
|
24
|
+
"replace all": "Reemplazar todo",
|
|
25
|
+
"close": "Cerrar",
|
|
26
|
+
"current match": "Coincidencia actual",
|
|
27
|
+
"on line": "en la línea",
|
|
28
|
+
"replaced match on line $": "Coincidencia reemplazada en la línea $",
|
|
29
|
+
"replaced $ matches": "$ coincidencias reemplazadas",
|
|
30
|
+
"Diagnostics": "Diagnósticos",
|
|
31
|
+
"No diagnostics": "Sin diagnósticos"
|
|
32
|
+
};
|
|
33
|
+
export default phrases;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Fixed CodeMirror lookup keys; preserve literal $ substitution tokens. */
|
|
2
|
+
const phrases = {
|
|
3
|
+
"Control character": "Caractère de contrôle",
|
|
4
|
+
"Selection deleted": "Sélection supprimée",
|
|
5
|
+
"Completions": "Suggestions",
|
|
6
|
+
"Folded lines": "Lignes repliées",
|
|
7
|
+
"Unfolded lines": "Lignes dépliées",
|
|
8
|
+
"Fold line": "Replier la ligne",
|
|
9
|
+
"Unfold line": "Déplier la ligne",
|
|
10
|
+
"folded code": "Code replié",
|
|
11
|
+
"unfold": "Déplier",
|
|
12
|
+
"to": "à",
|
|
13
|
+
"Go to line": "Aller à la ligne",
|
|
14
|
+
"go": "Aller",
|
|
15
|
+
"Find": "Rechercher",
|
|
16
|
+
"Replace": "Remplacer",
|
|
17
|
+
"next": "Suivant",
|
|
18
|
+
"previous": "Précédent",
|
|
19
|
+
"all": "Tout",
|
|
20
|
+
"match case": "Respecter la casse",
|
|
21
|
+
"regexp": "Expression régulière",
|
|
22
|
+
"by word": "Mots entiers",
|
|
23
|
+
"replace": "Remplacer",
|
|
24
|
+
"replace all": "Tout remplacer",
|
|
25
|
+
"close": "Fermer",
|
|
26
|
+
"current match": "Correspondance actuelle",
|
|
27
|
+
"on line": "à la ligne",
|
|
28
|
+
"replaced match on line $": "Correspondance remplacée à la ligne $",
|
|
29
|
+
"replaced $ matches": "$ correspondances remplacées",
|
|
30
|
+
"Diagnostics": "Diagnostics",
|
|
31
|
+
"No diagnostics": "Aucun diagnostic"
|
|
32
|
+
};
|
|
33
|
+
export default phrases;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Fixed CodeMirror lookup keys; preserve literal $ substitution tokens. */
|
|
2
|
+
const phrases = {
|
|
3
|
+
"Control character": "Carattere di controllo",
|
|
4
|
+
"Selection deleted": "Selezione eliminata",
|
|
5
|
+
"Completions": "Suggerimenti",
|
|
6
|
+
"Folded lines": "Righe compresse",
|
|
7
|
+
"Unfolded lines": "Righe espanse",
|
|
8
|
+
"Fold line": "Comprimi riga",
|
|
9
|
+
"Unfold line": "Espandi riga",
|
|
10
|
+
"folded code": "codice compresso",
|
|
11
|
+
"unfold": "espandi",
|
|
12
|
+
"to": "a",
|
|
13
|
+
"Go to line": "Vai alla riga",
|
|
14
|
+
"go": "Vai",
|
|
15
|
+
"Find": "Trova",
|
|
16
|
+
"Replace": "Sostituisci",
|
|
17
|
+
"next": "successivo",
|
|
18
|
+
"previous": "precedente",
|
|
19
|
+
"all": "tutti",
|
|
20
|
+
"match case": "distingui maiuscole e minuscole",
|
|
21
|
+
"regexp": "espressione regolare",
|
|
22
|
+
"by word": "parole intere",
|
|
23
|
+
"replace": "sostituisci",
|
|
24
|
+
"replace all": "sostituisci tutto",
|
|
25
|
+
"close": "chiudi",
|
|
26
|
+
"current match": "corrispondenza attuale",
|
|
27
|
+
"on line": "alla riga",
|
|
28
|
+
"replaced match on line $": "corrispondenza sostituita alla riga $",
|
|
29
|
+
"replaced $ matches": "$ corrispondenze sostituite",
|
|
30
|
+
"Diagnostics": "Diagnostica",
|
|
31
|
+
"No diagnostics": "Nessun messaggio di diagnostica"
|
|
32
|
+
};
|
|
33
|
+
export default phrases;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Fixed CodeMirror lookup keys; preserve literal $ substitution tokens. */
|
|
2
|
+
const phrases = {
|
|
3
|
+
"Control character": "制御文字",
|
|
4
|
+
"Selection deleted": "選択範囲を削除しました",
|
|
5
|
+
"Completions": "補完候補",
|
|
6
|
+
"Folded lines": "折りたたんだ行",
|
|
7
|
+
"Unfolded lines": "展開した行",
|
|
8
|
+
"Fold line": "行を折りたたむ",
|
|
9
|
+
"Unfold line": "行を展開",
|
|
10
|
+
"folded code": "折りたたんだコード",
|
|
11
|
+
"unfold": "展開",
|
|
12
|
+
"to": "から",
|
|
13
|
+
"Go to line": "指定行へ移動",
|
|
14
|
+
"go": "移動",
|
|
15
|
+
"Find": "検索",
|
|
16
|
+
"Replace": "置換",
|
|
17
|
+
"next": "次へ",
|
|
18
|
+
"previous": "前へ",
|
|
19
|
+
"all": "すべて",
|
|
20
|
+
"match case": "大文字と小文字を区別",
|
|
21
|
+
"regexp": "正規表現",
|
|
22
|
+
"by word": "単語単位",
|
|
23
|
+
"replace": "置換",
|
|
24
|
+
"replace all": "すべて置換",
|
|
25
|
+
"close": "閉じる",
|
|
26
|
+
"current match": "現在の一致箇所",
|
|
27
|
+
"on line": "行",
|
|
28
|
+
"replaced match on line $": "$ 行目の一致箇所を置換しました",
|
|
29
|
+
"replaced $ matches": "$ 件の一致箇所を置換しました",
|
|
30
|
+
"Diagnostics": "診断",
|
|
31
|
+
"No diagnostics": "診断結果はありません"
|
|
32
|
+
};
|
|
33
|
+
export default phrases;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Fixed CodeMirror lookup keys; preserve literal $ substitution tokens. */
|
|
2
|
+
const phrases = {
|
|
3
|
+
"Control character": "제어 문자",
|
|
4
|
+
"Selection deleted": "선택 영역 삭제됨",
|
|
5
|
+
"Completions": "자동 완성",
|
|
6
|
+
"Folded lines": "접힌 줄",
|
|
7
|
+
"Unfolded lines": "펼친 줄",
|
|
8
|
+
"Fold line": "줄 접기",
|
|
9
|
+
"Unfold line": "줄 펼치기",
|
|
10
|
+
"folded code": "접힌 코드",
|
|
11
|
+
"unfold": "펼치기",
|
|
12
|
+
"to": "~",
|
|
13
|
+
"Go to line": "줄로 이동",
|
|
14
|
+
"go": "이동",
|
|
15
|
+
"Find": "찾기",
|
|
16
|
+
"Replace": "바꾸기",
|
|
17
|
+
"next": "다음",
|
|
18
|
+
"previous": "이전",
|
|
19
|
+
"all": "모두",
|
|
20
|
+
"match case": "대소문자 구분",
|
|
21
|
+
"regexp": "정규식",
|
|
22
|
+
"by word": "단어 단위",
|
|
23
|
+
"replace": "바꾸기",
|
|
24
|
+
"replace all": "모두 바꾸기",
|
|
25
|
+
"close": "닫기",
|
|
26
|
+
"current match": "현재 일치 항목",
|
|
27
|
+
"on line": "줄",
|
|
28
|
+
"replaced match on line $": "$줄의 일치 항목을 바꿨습니다",
|
|
29
|
+
"replaced $ matches": "일치 항목 $개를 바꿨습니다",
|
|
30
|
+
"Diagnostics": "진단",
|
|
31
|
+
"No diagnostics": "진단 없음"
|
|
32
|
+
};
|
|
33
|
+
export default phrases;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Fixed CodeMirror lookup keys; preserve literal $ substitution tokens. */
|
|
2
|
+
const phrases = {
|
|
3
|
+
"Control character": "Caractere de controle",
|
|
4
|
+
"Selection deleted": "Seleção excluída",
|
|
5
|
+
"Completions": "Sugestões",
|
|
6
|
+
"Folded lines": "Linhas recolhidas",
|
|
7
|
+
"Unfolded lines": "Linhas expandidas",
|
|
8
|
+
"Fold line": "Recolher linha",
|
|
9
|
+
"Unfold line": "Expandir linha",
|
|
10
|
+
"folded code": "Código recolhido",
|
|
11
|
+
"unfold": "Expandir",
|
|
12
|
+
"to": "a",
|
|
13
|
+
"Go to line": "Ir para a linha",
|
|
14
|
+
"go": "Ir",
|
|
15
|
+
"Find": "Localizar",
|
|
16
|
+
"Replace": "Substituir",
|
|
17
|
+
"next": "Próximo",
|
|
18
|
+
"previous": "Anterior",
|
|
19
|
+
"all": "Tudo",
|
|
20
|
+
"match case": "Diferenciar maiúsculas e minúsculas",
|
|
21
|
+
"regexp": "Expressão regular",
|
|
22
|
+
"by word": "Palavras inteiras",
|
|
23
|
+
"replace": "Substituir",
|
|
24
|
+
"replace all": "Substituir tudo",
|
|
25
|
+
"close": "Fechar",
|
|
26
|
+
"current match": "Correspondência atual",
|
|
27
|
+
"on line": "na linha",
|
|
28
|
+
"replaced match on line $": "Correspondência substituída na linha $",
|
|
29
|
+
"replaced $ matches": "$ correspondências substituídas",
|
|
30
|
+
"Diagnostics": "Diagnósticos",
|
|
31
|
+
"No diagnostics": "Nenhum diagnóstico"
|
|
32
|
+
};
|
|
33
|
+
export default phrases;
|