@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 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.after-meta` 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.
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.after-meta` スロットへ、組み込みの LanguageSwitcher を登録します。標準 Site consumer がこのスロットを描画するため、l10n 専用の記事レイアウト実装は不要です。実在する翻訳が 2 つ未満のページには表示されません。
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.metadata?.[LANGUAGE_METADATA_KEY];
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.metadata?.[LANGUAGE_METADATA_KEY] ?? "",
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.metadata?.[LANGUAGE_METADATA_KEY] === lang
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.after-meta",
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 unlocalizedPermalink = removeLocalePathSegments(
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.metadata?.[LANGUAGE_METADATA_KEY] ?? "",
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.metadata?.[LANGUAGE_METADATA_KEY];
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,
@@ -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.after-meta` slot. */
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.15",
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.15"
19
+ "@riebeckite/core": "0.0.17"
20
20
  },
21
21
  "devDependencies": {
22
22
  "tsx": "^4.22.4",
23
- "@riebeckite/plugin-obsidian-markdown": "0.0.15"
23
+ "@riebeckite/plugin-obsidian-markdown": "0.0.17"
24
24
  },
25
25
  "publishConfig": {
26
26
  "access": "public"