@riebeckite/plugin-l10n 0.0.15 → 0.0.17
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/README.md +1 -1
- package/README_ja.md +3 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +25 -16
- package/dist/src/l10n.d.ts +2 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ No fallback pages are generated. `getLocalization(manifest, slug)` returns `avai
|
|
|
52
52
|
|
|
53
53
|
## Standard LanguageSwitcher
|
|
54
54
|
|
|
55
|
-
`l10n(...)` publishes the built-in, styled LanguageSwitcher in the standard `article.
|
|
55
|
+
`l10n(...)` publishes the built-in, styled LanguageSwitcher in the standard `article.metadata` layout slot. A standard Site consumer renders that slot, so no l10n-specific article integration is needed. It is omitted when a page has fewer than two real translations.
|
|
56
56
|
|
|
57
57
|
```ts
|
|
58
58
|
// Keep URLs and metadata but do not publish UI.
|
package/README_ja.md
CHANGED
|
@@ -37,7 +37,7 @@ translation: getting-started
|
|
|
37
37
|
|
|
38
38
|
## 標準 LanguageSwitcher
|
|
39
39
|
|
|
40
|
-
`l10n(...)` は標準記事レイアウトの `article.
|
|
40
|
+
`l10n(...)` は標準記事レイアウトの `article.metadata` スロットへ、組み込みの LanguageSwitcher を登録します。標準 Site consumer がこのスロットを描画するため、l10n 専用の記事レイアウト実装は不要です。実在する翻訳が 2 つ未満のページには表示されません。
|
|
41
41
|
|
|
42
42
|
```ts
|
|
43
43
|
// URL とメタデータは維持し、UI だけを無効化します。
|
|
@@ -71,7 +71,6 @@ l10n({
|
|
|
71
71
|
|
|
72
72
|
独自検出の言語は frontmatter より弱く、ファイル名・ディレクトリより強く扱われます。`translationId` は明示的な翻訳グループ ID です。
|
|
73
73
|
|
|
74
|
-
##
|
|
75
|
-
|
|
76
|
-
- [?????????](../../../docs/ja/docs/reference/plugin-api.md)
|
|
74
|
+
## 関連リンク
|
|
77
75
|
|
|
76
|
+
- [プラグイン API](../../../docs/ja/docs/reference/plugin-api.md)
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { getLocalization, getLocalizedContent, type L10nContent, type L10nDetectorContext, type L10nDetectorResult, type L10nOptions, type L10nUiOptions, type LanguageSwitcherRenderContext, type LocalizedContent, l10n, l10nPlugin, renderLanguageSwitcher, } from "./src/l10n.js";
|
|
1
|
+
export { getLanguageFromPath, getLocalization, getLocalizedContent, type L10nContent, type L10nDetectorContext, type L10nDetectorResult, type L10nOptions, type L10nUiOptions, type LanguageSwitcherRenderContext, type LocalizedContent, l10n, l10nPlugin, renderLanguageSwitcher, } from "./src/l10n.js";
|
package/dist/index.js
CHANGED
|
@@ -24,7 +24,6 @@ function renderLanguageSwitcher({
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// src/l10n.ts
|
|
27
|
-
var LANGUAGE_METADATA_KEY = "l10n.lang";
|
|
28
27
|
var TRANSLATION_METADATA_KEY = "l10n.translationId";
|
|
29
28
|
function l10n(options) {
|
|
30
29
|
const resolved = resolveOptions(options);
|
|
@@ -109,7 +108,7 @@ function splitLinkUrl(url) {
|
|
|
109
108
|
function getLocalization(manifest, slug) {
|
|
110
109
|
const entry = manifest.bySlug.get(slug);
|
|
111
110
|
if (!entry) return null;
|
|
112
|
-
const lang = entry.publicLocation.
|
|
111
|
+
const lang = entry.publicLocation.language;
|
|
113
112
|
const translationId = entry.publicLocation.metadata?.[TRANSLATION_METADATA_KEY];
|
|
114
113
|
if (!lang || !translationId) return null;
|
|
115
114
|
const candidates = manifest.discoverableEntries.filter(
|
|
@@ -117,7 +116,7 @@ function getLocalization(manifest, slug) {
|
|
|
117
116
|
);
|
|
118
117
|
const translations = Object.fromEntries(
|
|
119
118
|
uniqueLanguageEntries(candidates).map((candidate) => [
|
|
120
|
-
candidate.publicLocation.
|
|
119
|
+
candidate.publicLocation.language ?? "",
|
|
121
120
|
candidate.permalink
|
|
122
121
|
])
|
|
123
122
|
);
|
|
@@ -134,10 +133,17 @@ function getLocalizedContent(manifest, slug, lang) {
|
|
|
134
133
|
const localization = getLocalization(manifest, slug);
|
|
135
134
|
if (!localization) return null;
|
|
136
135
|
const candidates = manifest.publicEntries.filter(
|
|
137
|
-
(entry) => entry.publicLocation.metadata?.[TRANSLATION_METADATA_KEY] === localization.translationId && entry.publicLocation.
|
|
136
|
+
(entry) => entry.publicLocation.metadata?.[TRANSLATION_METADATA_KEY] === localization.translationId && entry.publicLocation.language === lang
|
|
138
137
|
);
|
|
139
138
|
return candidates.length === 1 ? candidates[0] ?? null : null;
|
|
140
139
|
}
|
|
140
|
+
function getLanguageFromPath(manifest, pathname) {
|
|
141
|
+
const firstSegment = pathname.split("/").filter(Boolean)[0];
|
|
142
|
+
if (!firstSegment) return void 0;
|
|
143
|
+
return manifest.discoverableEntries.map((entry) => entry.publicLocation.language).find(
|
|
144
|
+
(language) => language?.toLocaleLowerCase() === firstSegment.toLocaleLowerCase()
|
|
145
|
+
);
|
|
146
|
+
}
|
|
141
147
|
function resolveOptions(options) {
|
|
142
148
|
const validation = validateOptions(options);
|
|
143
149
|
if (validation.length > 0) throw new Error(validation.join("\n"));
|
|
@@ -201,7 +207,7 @@ function validateOptions(options) {
|
|
|
201
207
|
function resolveUiOptions(ui) {
|
|
202
208
|
if (ui === false) return false;
|
|
203
209
|
return {
|
|
204
|
-
slot: ui?.slot ?? "article.
|
|
210
|
+
slot: ui?.slot ?? "article.metadata",
|
|
205
211
|
render: ui?.render ?? renderLanguageSwitcher
|
|
206
212
|
};
|
|
207
213
|
}
|
|
@@ -336,21 +342,25 @@ function readTranslationId(value) {
|
|
|
336
342
|
return value.trim();
|
|
337
343
|
}
|
|
338
344
|
function withLocalization(location, content, options) {
|
|
339
|
-
const
|
|
340
|
-
location.permalink,
|
|
341
|
-
content
|
|
342
|
-
);
|
|
343
|
-
const permalink = content.lang === options.defaultLang ? unlocalizedPermalink : prefixLanguage(unlocalizedPermalink, content.lang);
|
|
345
|
+
const permalink = localizePath(location.permalink, content, options);
|
|
344
346
|
return {
|
|
345
347
|
...location,
|
|
346
348
|
permalink,
|
|
349
|
+
language: content.lang,
|
|
350
|
+
redirects: location.redirects?.map((redirect) => ({
|
|
351
|
+
...redirect,
|
|
352
|
+
path: localizePath(redirect.path, content, options)
|
|
353
|
+
})),
|
|
347
354
|
metadata: {
|
|
348
355
|
...location.metadata,
|
|
349
|
-
[LANGUAGE_METADATA_KEY]: content.lang,
|
|
350
356
|
[TRANSLATION_METADATA_KEY]: content.translationId
|
|
351
357
|
}
|
|
352
358
|
};
|
|
353
359
|
}
|
|
360
|
+
function localizePath(pathname, content, options) {
|
|
361
|
+
const unlocalizedPath = removeLocalePathSegments(pathname, content);
|
|
362
|
+
return content.lang === options.defaultLang ? unlocalizedPath : prefixLanguage(unlocalizedPath, content.lang);
|
|
363
|
+
}
|
|
354
364
|
function removeLocalePathSegments(permalink, content) {
|
|
355
365
|
let result = permalink;
|
|
356
366
|
const filenameLanguage = content.signals.filename;
|
|
@@ -400,7 +410,7 @@ function addLocalizationHeadTags(manifest, state) {
|
|
|
400
410
|
tag: "link",
|
|
401
411
|
attrs: {
|
|
402
412
|
rel: "alternate",
|
|
403
|
-
hreflang: translation.publicLocation.
|
|
413
|
+
hreflang: translation.publicLocation.language ?? "",
|
|
404
414
|
href: translation.permalink
|
|
405
415
|
}
|
|
406
416
|
})
|
|
@@ -429,10 +439,8 @@ function sameHeadTag(left, right) {
|
|
|
429
439
|
}
|
|
430
440
|
function uniqueLanguageEntries(entries) {
|
|
431
441
|
return entries.filter((entry) => {
|
|
432
|
-
const lang = entry.publicLocation.
|
|
433
|
-
return lang !== void 0 && entries.filter(
|
|
434
|
-
(other) => other.publicLocation.metadata?.[LANGUAGE_METADATA_KEY] === lang
|
|
435
|
-
).length === 1;
|
|
442
|
+
const lang = entry.publicLocation.language;
|
|
443
|
+
return lang !== void 0 && entries.filter((other) => other.publicLocation.language === lang).length === 1;
|
|
436
444
|
});
|
|
437
445
|
}
|
|
438
446
|
function compactSignals(signals) {
|
|
@@ -499,6 +507,7 @@ function emptyState() {
|
|
|
499
507
|
};
|
|
500
508
|
}
|
|
501
509
|
export {
|
|
510
|
+
getLanguageFromPath,
|
|
502
511
|
getLocalization,
|
|
503
512
|
getLocalizedContent,
|
|
504
513
|
l10n,
|
package/dist/src/l10n.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export type L10nOptions = {
|
|
|
25
25
|
ui?: L10nUiOptions;
|
|
26
26
|
};
|
|
27
27
|
export type L10nUiOptions = false | {
|
|
28
|
-
/** Defaults to the standard `article.
|
|
28
|
+
/** Defaults to the standard `article.metadata` slot. */
|
|
29
29
|
slot?: ContentBodySlot;
|
|
30
30
|
/** Replaces the built-in server-rendered LanguageSwitcher. */
|
|
31
31
|
render?: (context: LanguageSwitcherRenderContext) => string | null;
|
|
@@ -47,4 +47,5 @@ export declare const l10nPlugin: typeof l10n;
|
|
|
47
47
|
export declare function getLocalization(manifest: ContentManifest, slug: string): LocalizedContent | null;
|
|
48
48
|
/** Resolves an existing translation; missing translations return `null`. */
|
|
49
49
|
export declare function getLocalizedContent(manifest: ContentManifest, slug: string, lang: string): ContentManifestEntry | null;
|
|
50
|
+
export declare function getLanguageFromPath(manifest: ContentManifest, pathname: string): string | undefined;
|
|
50
51
|
export { renderLanguageSwitcher } from "./language-switcher.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@riebeckite/plugin-l10n",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.17",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"yaml": "^2.9.0",
|
|
19
|
-
"@riebeckite/core": "0.0.
|
|
19
|
+
"@riebeckite/core": "0.0.17"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"tsx": "^4.22.4",
|
|
23
|
-
"@riebeckite/plugin-obsidian-markdown": "0.0.
|
|
23
|
+
"@riebeckite/plugin-obsidian-markdown": "0.0.17"
|
|
24
24
|
},
|
|
25
25
|
"publishConfig": {
|
|
26
26
|
"access": "public"
|