typesafe-i18n icon indicating copy to clipboard operation
typesafe-i18n copied to clipboard

Vue: namespace not being loaded

Open PindaPixel opened this issue 8 months ago • 0 comments

Version

5.26.2

Describe the bug

When loadNamespaceAsync has resolved, the namespace is still undefined in LL.

Reproduction

// main.ts
import { createApp } from "vue";

import { i18nPlugin } from "@/Assets/i18n/i18n-vue";
import { detectLocale } from "@/Assets/i18n/i18n-util";
import { loadLocaleAsync } from "@/Assets/i18n/i18n-util.async";
import { navigatorDetector } from "typesafe-i18n/detectors";

import App from "./App.vue";

const app = createApp(App);

const detectedLocale = detectLocale(navigatorDetector);

loadLocaleAsync(detectedLocale).then(() => {
    app.use(i18nPlugin, detectedLocale);
    app.mount("#app-root");
});
// Locale.ts
import { typesafeI18n } from "@/Assets/i18n/i18n-vue";
import { loadNamespaceAsync } from "@/Assets/i18n/i18n-util.async";
import {
    type Locales,
    type Namespaces,
    type TranslationFunctions,
} from "@/Assets/i18n/i18n-types";
import { computed, ref, type Ref } from "vue";

const loadedNamespaces = ref<Set<Namespaces>>(new Set());

export function useLocaleNameSpace<T extends Namespaces>(
    nameSpace: T,
): Ref<TranslationFunctions[T] | null> {
    const { LL, locale } = typesafeI18n();
    const ready = computed(() => loadedNamespaces.value.has(nameSpace));

    if (!ready.value)
        loadNamespaceAsync(locale.value, nameSpace).then(() => {
            loadedNamespaces.value.add(nameSpace);
        });

    return computed(() => {
        return ready.value ? LL.value[nameSpace] : null;
    });
}

export function useLocaleCommon() {
    const { LL } = typesafeI18n();

    return LL as Omit<typeof LL, Namespaces>;
}

export function useSetLocale() {
    const { setLocale: _setLocale } = typesafeI18n();

    return (locale: Locales) => {
        _setLocale(locale);
        loadedNamespaces.value.clear();
    };
}
// src/Assets/i18n/en/reports/index.ts
import type { BaseTranslation } from "../../i18n-types";

export default {
    adminReports: "Administration",
    eac: "Estimate At Completion",
    eacManual: "EAC Manual",
    eac_min: "Estimate",
    header1: "Code",
    header2: "Task",
    header3: "Header3",
    header4: "Header4",
    header5: "Header5",
    hoursReports: "Hours",
    invalidSourceCurve: "Invalid source curve '{0}'",
    invalidTargetCurve: "Invalid target curve '{0}'",
    noFilters: "No filters",
    noSourceScurveData:
        "No scurve data for source component 'sourceComponentId: {0}|sourceCurve: {1}'",
    noTargetAssignmentHourDistribution:
        "No AssignmentHourDistribution data for target component: '{0}|type: {1}'",
    noTargetComponentActivities:
        "No activities for target component 'targetComponentId: {0}'",
    planningReports: "Planning",
    reportData: "Report Data",
    showHideMarkers: "Show/hide Markers",
    showReportData: "Show Report Data",
    text1FilterPlaceholder: "Example: 1230,1240,1250",
    text2FilterPlaceholder: "Example: 1230,1240,1250",
    text3FilterPlaceholder: "Example: 1230,1240,1250",
    text4FilterPlaceholder: "Example: 1230,1240,1250",
    text5FilterPlaceholder: "Example: 1230,1240,1250",
    worklistPerProject: "Worklist per project",
    worklistPerProjectFileName: "worklist-per-project",
    worklistPerProjectQr: "Worklist per project (QR)",
} satisfies BaseTranslation;
<!-- ReportPage.vue -->
<script setup lang="ts">
import { useLocaleNameSpace } from "@/Composables/Locale";

const LL = useLocaleNameSpace("reports");
</script>

<template>
    <div v-if="LL">
        Ready
        {{ LL.invalidSourceCurve("test") }}
    </div>
    <div v-if="!LL">Loading</div>
</template>

Renders: Ready

Logs

No response

Config

// .typesafe-i18n.json
{
   "adapter": "vue",
   "esmImports": true,
   "outputPath": "./src/Assets/i18n",
   "$schema": "https://unpkg.com/[email protected]/schema/typesafe-i18n.json"
}

Additional information

No response

PindaPixel avatar Nov 21 '23 15:11 PindaPixel