From 4295a83ee102a4841d9cbf282f6e75b00ed1283e Mon Sep 17 00:00:00 2001
From: Benjamin Singleton <19498453+tetrogem@users.noreply.github.com>
Date: Mon, 23 Mar 2026 16:52:13 -0500
Subject: [PATCH] feat(i18n): first draft of vi18n lib
---
apps/vdn-static/src/App.vue | 2 +-
.../src/components/atoms/MarkdownDisplay.vue | 4 +-
.../src/components/atoms/MarkdownParts.vue | 4 +-
.../src/components/atoms/RichText.vue | 31 -------
.../molecules/DiscordRuleOverview.vue | 4 +-
.../molecules/DiscordRuleSection.vue | 2 +-
.../src/components/organisms/LocalePicker.vue | 2 +-
.../src/{new-i18n => i18n}/config.ts | 24 ++---
.../src/{new-i18n => i18n}/greeting.ts | 0
.../src/{new-i18n => i18n}/index.ts | 30 +++++--
.../src/{new-i18n => i18n}/vilantic.ts | 0
apps/vdn-static/src/pages/discord/rules.vue | 2 +-
apps/vdn-static/src/pages/index.vue | 8 +-
apps/vdn-static/src/pages/kotoba.vue | 2 +-
apps/vdn-static/src/pages/resources.vue | 4 +-
.../{new-i18n-lib => vi18n-lib}/compile.ts | 90 +++++++++++++++----
.../src/{new-i18n-lib => vi18n-lib}/config.ts | 29 ++----
.../{new-i18n-lib => vi18n-lib}/markdown.ts | 88 ++++++++++++------
.../src/{new-i18n-lib => vi18n-lib}/setup.ts | 0
.../src/{new-i18n-lib => vi18n-lib}/spec.md | 0
20 files changed, 194 insertions(+), 132 deletions(-)
delete mode 100644 apps/vdn-static/src/components/atoms/RichText.vue
rename apps/vdn-static/src/{new-i18n => i18n}/config.ts (87%)
rename apps/vdn-static/src/{new-i18n => i18n}/greeting.ts (100%)
rename apps/vdn-static/src/{new-i18n => i18n}/index.ts (85%)
rename apps/vdn-static/src/{new-i18n => i18n}/vilantic.ts (100%)
rename apps/vdn-static/src/{new-i18n-lib => vi18n-lib}/compile.ts (88%)
rename apps/vdn-static/src/{new-i18n-lib => vi18n-lib}/config.ts (89%)
rename apps/vdn-static/src/{new-i18n-lib => vi18n-lib}/markdown.ts (92%)
rename apps/vdn-static/src/{new-i18n-lib => vi18n-lib}/setup.ts (100%)
rename apps/vdn-static/src/{new-i18n-lib => vi18n-lib}/spec.md (100%)
diff --git a/apps/vdn-static/src/App.vue b/apps/vdn-static/src/App.vue
index 022c5de..517c29a 100644
--- a/apps/vdn-static/src/App.vue
+++ b/apps/vdn-static/src/App.vue
@@ -6,7 +6,7 @@ import { vOnClickOutside } from "@vueuse/components";
import { useRouter } from "vue-router";
import SmartLink from "./components/atoms/SmartLink.vue";
import type { SmartDest } from "./utils/smart-dest";
-import { useLocale, type Locale } from "./new-i18n";
+import { useLocale, type Locale } from "./i18n";
const locale = useLocale();
diff --git a/apps/vdn-static/src/components/atoms/MarkdownDisplay.vue b/apps/vdn-static/src/components/atoms/MarkdownDisplay.vue
index daaa4f7..76601d9 100644
--- a/apps/vdn-static/src/components/atoms/MarkdownDisplay.vue
+++ b/apps/vdn-static/src/components/atoms/MarkdownDisplay.vue
@@ -7,7 +7,7 @@ import {
} from "vue";
import MarkdownParts from "./MarkdownParts.vue";
import OptionalParent from "./OptionalParent.vue";
-import type { Markdown } from "@/new-i18n-lib/markdown";
+import type { Markdown } from "@/vi18n-lib/markdown";
import type { CssClass } from "@/utils/css";
const props = defineProps<{
@@ -58,7 +58,7 @@ const getComponentStack = () => {
// Validate required slots at runtime
onMounted(() => {
const requiredSlots = props.markdown.slots;
- const missingSlots = requiredSlots.filter(
+ const missingSlots = [...requiredSlots].filter(
(slot) => providedSlots[slot] === undefined,
);
diff --git a/apps/vdn-static/src/components/atoms/MarkdownParts.vue b/apps/vdn-static/src/components/atoms/MarkdownParts.vue
index 708be6b..ce852d5 100644
--- a/apps/vdn-static/src/components/atoms/MarkdownParts.vue
+++ b/apps/vdn-static/src/components/atoms/MarkdownParts.vue
@@ -1,12 +1,12 @@
-
-
-
-
- {{ part }}
-
-
-
-
-
-
-
-
-
diff --git a/apps/vdn-static/src/components/molecules/DiscordRuleOverview.vue b/apps/vdn-static/src/components/molecules/DiscordRuleOverview.vue
index 76914c5..2332a57 100644
--- a/apps/vdn-static/src/components/molecules/DiscordRuleOverview.vue
+++ b/apps/vdn-static/src/components/molecules/DiscordRuleOverview.vue
@@ -2,9 +2,9 @@
import SmartLink from "../atoms/SmartLink.vue";
import type { Value } from "@/utils/types";
import MarkdownDisplay from "../atoms/MarkdownDisplay.vue";
-import type { Locale } from "@/new-i18n";
+import type { Locale } from "@/i18n";
import type { DeepReadonly } from "vue";
-import { isEmptyMarkdown } from "@/new-i18n-lib/markdown";
+import { isEmptyMarkdown } from "@/vi18n-lib/markdown";
const props = defineProps<{
overview: DeepReadonly<
diff --git a/apps/vdn-static/src/components/molecules/DiscordRuleSection.vue b/apps/vdn-static/src/components/molecules/DiscordRuleSection.vue
index a4adb7b..64c5871 100644
--- a/apps/vdn-static/src/components/molecules/DiscordRuleSection.vue
+++ b/apps/vdn-static/src/components/molecules/DiscordRuleSection.vue
@@ -1,5 +1,5 @@
diff --git a/apps/vdn-static/src/pages/resources.vue b/apps/vdn-static/src/pages/resources.vue
index bba9089..3d3e5e3 100644
--- a/apps/vdn-static/src/pages/resources.vue
+++ b/apps/vdn-static/src/pages/resources.vue
@@ -2,8 +2,8 @@
import LearningResourceWrapper, {
type ResourceButton,
} from "@/components/molecules/LearningResourceWrapper.vue";
-import { useLocale, type Locale } from "@/new-i18n";
-import type * as i18n from "@/new-i18n/config";
+import { useLocale, type Locale } from "@/i18n";
+import type * as i18n from "@/i18n/config";
import { ignore } from "@/utils/ignore";
import { computed } from "vue";
import discordImg from "@/assets/discord.png";
diff --git a/apps/vdn-static/src/new-i18n-lib/compile.ts b/apps/vdn-static/src/vi18n-lib/compile.ts
similarity index 88%
rename from apps/vdn-static/src/new-i18n-lib/compile.ts
rename to apps/vdn-static/src/vi18n-lib/compile.ts
index 9727835..294b23c 100644
--- a/apps/vdn-static/src/new-i18n-lib/compile.ts
+++ b/apps/vdn-static/src/vi18n-lib/compile.ts
@@ -30,7 +30,9 @@ type GenericMarkdownMessageFn = (
placeableArgs?: GenericMessageFnPlaceableArgs,
) => Markdown;
-type GenericMessageFnPlaceableArgs = Record;
+type GenericMessageFnPlaceableArgs = Record;
+
+type PlaceableValue = string | number;
export interface CompileLocaleCtx {
bundle: FluentBundle;
@@ -42,7 +44,7 @@ export interface CompileLocaleCtx {
export interface CompileLocaleRes {
locale: Locale;
- errors: string[];
+ errors: readonly string[];
}
export function compileLocale(
@@ -122,7 +124,7 @@ export function compileLocale(
return () =>
createMissingMarkdownFallback(
valueMessageIdChain,
- Object.keys(configValue.features.slots),
+ new Set(Object.keys(configValue.slots)),
);
}
}
@@ -263,7 +265,7 @@ function compileMessage(
case configMarkdownSymbol: {
return compileMarkdownMessage({
bundle,
- configMarkdown: configValue,
+ slots: new Set(Object.keys(configValue.slots)),
messageIdChain,
allVariants,
pattern,
@@ -309,7 +311,7 @@ function compileStringMessage(
// TODO: will need to make sure markdown/slots are escapes when inserting variable values
return {
type: "ok",
- ok: (args: Record = {}) => {
+ ok: (args: Record = {}) => {
const stringRes = ((): Result => {
const stringLiteralRes = parseMessageLiteral(
"string",
@@ -361,7 +363,7 @@ function compileStringMessage(
interface CompileMarkdownMessageCtx {
bundle: FluentBundle;
messageIdChain: readonly [...string[], string];
- configMarkdown: ConfigMarkdown