Skip to content

Commit

Permalink
Update Nuxt i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
obulat committed Nov 20, 2024
1 parent d2e57e4 commit 1cf820e
Show file tree
Hide file tree
Showing 45 changed files with 603 additions and 426 deletions.
12 changes: 6 additions & 6 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ coverage
*.pot

# Downloaded translation files
src/locales/openverse.zip
src/locales/*.json
src/locales/scripts/valid-locales.json
src/locales/scripts/untranslated-locales.json
src/locales/scripts/invalid-locales.json
src/locales/scripts/wp-locales.json
i18n/locales/openverse.zip
i18n/locales/*.json
i18n/locales/scripts/valid-locales.json
i18n/locales/scripts/untranslated-locales.json
i18n/locales/scripts/invalid-locales.json
i18n/locales/scripts/wp-locales.json

# Workspace mock-files
/.npmrc
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const axios = require("axios")

const { userAgent } = require("../../constants/user-agent")
const { userAgent } = require("../../../src/constants/user-agent")

module.exports = module.exports = axios.create({
headers: { "User-Agent": userAgent },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const fetchBulkJed1x = async () => {
params: { "export-format": "jed1x" },
responseType: "stream",
})
const destPath = process.cwd() + "/src/locales/openverse.zip"
const destPath = process.cwd() + "/i18n/locales/openverse.zip"
await pipeline(res.data, createWriteStream(destPath))
return destPath
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ async function getWpLocaleData() {
getWpLocaleData()
.then((data) => {
try {
const fileName = process.cwd() + "/src/locales/scripts/wp-locales.json"
const fileName = process.cwd() + "/i18n/locales/scripts/wp-locales.json"
fs.writeFileSync(fileName, JSON.stringify(data, null, 2) + "\n")
console.log(`Successfully wrote locales list file to ${fileName}`)
} catch (err) {
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const { parseJson } = require("./read-i18n")
const writeEnglish = () => {
const rootEntry = parseJson("en.json5")
writeFileSync(
process.cwd() + "/src/locales/en.json",
process.cwd() + "/i18n/locales/en.json",
JSON.stringify(rootEntry, null, 2) + os.EOL
)
console.log("Successfully saved English translation to en.json.")
Expand All @@ -26,7 +26,7 @@ writeEnglish()
if (process.argv.includes("--watch")) {
console.log("Watching en.json5 for changes...")
chokidar
.watch(process.cwd() + "/src/locales/scripts/en.json5")
.watch(process.cwd() + "/i18n/locales/scripts/en.json5")
.on("all", (event, path) => {
console.log(`Event '${event}' for file ${path}`)
writeEnglish()
Expand All @@ -46,7 +46,7 @@ if (!process.argv.includes("--en-only")) {
} else {
// Create valid-locales.json if it doesn't exist. It is required for Nuxt to build the app.
const validLocalesFilePath =
process.cwd() + "/src/locales/scripts/valid-locales.json"
process.cwd() + "/i18n/locales/scripts/valid-locales.json"
if (!existsSync(validLocalesFilePath)) {
writeFileSync(validLocalesFilePath, "[]")
console.log("Created empty valid-locales.json.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const getValidatedLocales = async () => {
translated: locale.translated,
}))
for (const locale of allLocales) {
const fileLocation = `${process.cwd()}/src/locales/${locale.file}`
const fileLocation = `${process.cwd()}/i18n/locales/${locale.file}`
if (fs.existsSync(fileLocation)) {
if (Object.keys(JSON.parse(fs.readFileSync(fileLocation))).length) {
result.translated.push(locale)
Expand All @@ -59,7 +59,7 @@ try {
const fileName = "valid-locales.json"
const valid = locales.translated
fs.writeFileSync(
process.cwd() + `/src/locales/scripts/` + fileName,
process.cwd() + `/i18n/locales/scripts/` + fileName,
JSON.stringify(valid, null, 2) + "\n"
)

Expand All @@ -68,14 +68,14 @@ try {
)
const untranslatedFileName = "untranslated-locales.json"
fs.writeFileSync(
process.cwd() + `/src/locales/scripts/` + untranslatedFileName,
process.cwd() + `/i18n/locales/scripts/` + untranslatedFileName,
JSON.stringify(locales.untranslated, null, 2) + "\n"
)

console.log(`Found ${locales.invalid.length} invalid locales.`)
const invalidFileName = "invalid-locales.json"
fs.writeFileSync(
process.cwd() + `/src/locales/scripts/` + invalidFileName,
process.cwd() + `/i18n/locales/scripts/` + invalidFileName,
JSON.stringify(locales.invalid, null, 2) + "\n"
)

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@ const path = require("path")

const glob = require("glob")

const BASE_PATH = path.dirname(path.dirname(__dirname))
const BASE_PATH = path.join(
path.dirname(path.dirname(path.dirname(__dirname))),
"src"
)

function readVueFiles(src) {
const targetFiles = glob.sync(src)

if (targetFiles.length === 0) {
throw new Error("vueFiles glob has no files.")
}
// Now that the script are inside `src/locales/scripts`,
// to get relative URL, the script needs to go up 3 levels
// Now that the script are inside `i18n/locales/scripts`,
// to get relative URL, the script needs to go up 4 levels
return targetFiles.map((f) => {
const fileName = path.relative(process.cwd(), f.replace(BASE_PATH, "src"))
return {
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ exports.writeLocaleFile = (locale, rawTranslations, deprecatedKeys) => {
)

return writeFile(
process.cwd() + `/src/locales/${locale}.json`,
process.cwd() + `/i18n/locales/${locale}.json`,
JSON.stringify(translations, null, 2) + os.EOL
)
}
39 changes: 39 additions & 0 deletions frontend/i18n/vue-i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { defineI18nConfig } from "#imports"

// import fallbackLocale from "~/locales/scripts/locale-fallback.json"

export default defineI18nConfig(() => {
return {
legacy: false,
globalInjection: true,
fallbackLocale: "en",
silentFallbackWarn: true,
pluralizationRules: {
/**
* @param choice - a choice index given by the input to $tc: $tc('header.filterButton.withCount', choiceIndex)
* @param choicesLength - an overall amount of available choices
* @returns a final choice index to select plural word by
*/
ru: function (choice: number, choicesLength: number) {
if (choice === 0) {
return 0
}

const teen = choice > 10 && choice < 20
const endsWithOne = choice % 10 === 1

if (choicesLength < 4) {
return !teen && endsWithOne ? 1 : 2
}
if (!teen && endsWithOne) {
return 1
}
if (!teen && choice % 10 >= 2 && choice % 10 <= 4) {
return 2
}

return choicesLength < 4 ? 2 : 3
},
},
}
})
3 changes: 1 addition & 2 deletions frontend/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineNuxtConfig } from "nuxt/config"

import { disallowedBots } from "./src/constants/disallowed-bots"
import locales from "./src/locales/scripts/valid-locales.json"
import locales from "./i18n/locales/scripts/valid-locales.json"

import type { LocaleObject } from "@nuxtjs/i18n"

Expand Down Expand Up @@ -124,6 +124,5 @@ export default defineNuxtConfig({
* */
detectBrowserLanguage: false,
trailingSlash: false,
vueI18n: "./src/vue-i18n",
},
})
17 changes: 9 additions & 8 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@
"test:storybook:local": "playwright test -c test/storybook",
"test:storybook:debug": "PWDEBUG=1 pnpm test:storybook:local",
"test:storybook:gen": "playwright codegen localhost:54000/",
"types": "pnpm run prepare:nuxt && vue-tsc -p .",
"types": "pnpm run i18n:copy-test-locales && pnpm run prepare:nuxt && vue-tsc -p .",
"i18n": "pnpm i18n:create-locales-list && pnpm i18n:get-translations && pnpm i18n:update-locales",
"i18n:en": "pnpm i18n:get-translations --en-only",
"i18n:copy-test-locales": "cp test/locales/**.json src/locales/ && mv src/locales/valid-locales.json src/locales/scripts/valid-locales.json",
"i18n:copy-test-locales": "cp test/locales/**.json i18n/locales/ && mv i18n/locales/valid-locales.json i18n/locales/scripts/valid-locales.json",
"i18n:no-get": "pnpm i18n:create-locales-list && pnpm i18n:update-locales",
"i18n:create-locales-list": "node src/locales/scripts/create-wp-locale-list",
"i18n:get-translations": "node src/locales/scripts/get-translations",
"i18n:update-locales": "node src/locales/scripts/get-validated-locales",
"i18n:generate-pot": "node src/locales/scripts/json-to-pot",
"i18n:check": "vue-i18n-extract report --vueFiles './src/*/**.?(js|ts|vue)' --languageFiles './src/locales/en.json'",
"i18n:create-locales-list": "node i18n/locales/scripts/create-wp-locale-list",
"i18n:get-translations": "node i18n/locales/scripts/get-translations",
"i18n:update-locales": "node i18n/locales/scripts/get-validated-locales",
"i18n:generate-pot": "node i18n/locales/scripts/json-to-pot",
"i18n:check": "vue-i18n-extract report --vueFiles './src/*/**.?(js|ts|vue)' --languageFiles './i18n/locales/en.json'",
"create:component-sfc": "remake component",
"create:story": "remake story",
"create:component-storybook-test": "remake component-storybook-test",
Expand Down Expand Up @@ -86,8 +86,9 @@
},
"devDependencies": {
"@babel/parser": "^7.24.8",
"@intlify/core-base": "^10.0.4",
"@nuxt/test-utils": "^3.14.4",
"@nuxtjs/i18n": "8.5.5",
"@nuxtjs/i18n": "^9.1.0",
"@nuxtjs/storybook": "8.3.2",
"@playwright/test": "1.48.2",
"@storybook-vue/nuxt": "8.3.2",
Expand Down
8 changes: 2 additions & 6 deletions frontend/src/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,7 @@ const headerHeight = computed(() => {
return `--header-height: ${uiStore.headerHeight}px`
})
const head = useLocaleHead({
addDirAttribute: true,
identifierAttribute: "id",
addSeoAttributes: true,
})
const head = useLocaleHead({ dir: true, key: "id", seo: true })
useHead({
bodyAttrs: { class: darkMode.cssClass },
Expand Down Expand Up @@ -78,7 +74,7 @@ onMounted(() => {

<template>
<div>
<Html :lang="head.htmlAttrs.lang" :dir="head.htmlAttrs.dir">
<Html :lang="head.htmlAttrs?.lang" :dir="head.htmlAttrs?.dir">
<Head>
<template v-for="link in head.link" :key="link.id">
<Link
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/VErrorSection/VErrorImage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const props = defineProps<{
errorCode: "NO_RESULT" | "SERVER_TIMEOUT"
}>()
const i18n = useI18n({ useScope: "global" })
const { t } = useI18n({ useScope: "global" })
const images = Object.fromEntries(
imageInfo.errors.map((errorItem) => {
Expand All @@ -38,7 +38,7 @@ const images = Object.fromEntries(
license_version: image.license_version as LicenseVersion,
frontendMediaType: "image",
}
errorImage.attribution = getAttribution(errorImage, i18n)
errorImage.attribution = getAttribution(errorImage, t)
return [errorItem.error, errorImage]
})
)
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/VLicense/VLicense.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ const props = withDefaults(
const { effectiveColorMode } = useDarkMode()
const i18n = useI18n({ useScope: "global" })
const { t } = useI18n({ useScope: "global" })
const iconNames = computed(() => getElements(props.license))
const licenseName = computed(() => {
const licenseKey =
props.license === "sampling+" ? props.license : camelCase(props.license)
return {
readable: i18n.t(`licenseReadableNames.${licenseKey}`),
full: getFullLicenseName(props.license, "", i18n),
readable: t(`licenseReadableNames.${licenseKey}`),
full: getFullLicenseName(props.license, "", t),
}
})
</script>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/VMediaInfo/VCopyLicense.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ const props = defineProps<{ media: Media }>()
const richRef = ref<HTMLElement | null>(null)
const i18n = useI18n({ useScope: "global" })
const { t } = useI18n({ useScope: "global" })
const getAttributionMarkup = (options?: AttributionOptions) =>
getAttribution(props.media, i18n, options)
getAttribution(props.media, t, options)
const { $sendCustomEvent } = useNuxtApp()
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/VMediaInfo/VMediaDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import VMediaTags from "~/components/VMediaInfo/VMediaTags.vue"
const props = defineProps<{ media: AudioDetail | ImageDetail }>()
const i18n = useI18n({ useScope: "global" })
const { t } = useI18n({ useScope: "global" })
const metadata = computed<null | Metadata[]>(() => {
if (!props.media) {
Expand All @@ -28,7 +28,7 @@ const metadata = computed<null | Metadata[]>(() => {
type: props.media.filetype,
}
: {}
return getMediaMetadata(props.media, i18n, imageInfo)
return getMediaMetadata(props.media, t, imageInfo)
})
</script>

Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/VMediaInfo/VMediaLicense.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,16 @@ const props = defineProps<{
licenseUrl: string
}>()
const i18n = useI18n({ useScope: "global" })
const { t } = useI18n({ useScope: "global" })
const { $sendCustomEvent } = useNuxtApp()
const isLicense = computed(() => isLicenseFn(props.license))
const headerText = computed(() => {
const licenseOrTool = isLicense.value ? "license" : "tool"
return i18n.t(`mediaDetails.reuse.${licenseOrTool}Header`)
return t(`mediaDetails.reuse.${licenseOrTool}Header`)
})
const fullLicenseName = computed(() =>
getFullLicenseName(props.license, props.licenseVersion, i18n)
getFullLicenseName(props.license, props.licenseVersion, t)
)
const sendVisitLicensePage = () => {
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/components/VMediaInfo/meta/VMetadata.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,18 @@ const Template: Omit<Story, "args"> = {
},
sourceNames: { audio: [testAudio.source], image: [testImage.source] },
})
const i18n = useI18n({ useScope: "global" })
const { t } = useI18n({ useScope: "global" })
const data = [
{
metadata: getMediaMetadata(testImage, i18n, {
metadata: getMediaMetadata(testImage, t, {
width: testImage.width,
height: testImage.height,
type: testImage.filetype,
}),
media: testImage,
},
{
metadata: getMediaMetadata(testAudio, i18n),
metadata: getMediaMetadata(testAudio, t),
media: testAudio,
},
]
Expand Down
11 changes: 5 additions & 6 deletions frontend/src/composables/use-collection-meta.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { useI18n } from "#imports"

import { computed } from "vue"

import { useProviderStore } from "~/stores/provider"
import type { SupportedMediaType } from "~/constants/media"
import type { CollectionParams } from "~/types/search"

import type { ComputedRef } from "vue"
import type { Composer } from "vue-i18n"

export const useCollectionMeta = ({
collectionParams,
mediaType,
i18n,
t,
}: {
collectionParams: ComputedRef<CollectionParams | null>
mediaType: SupportedMediaType
i18n: ReturnType<typeof useI18n>
t: Composer["t"]
}) => {
const pageTitle = computed(() => {
const params = collectionParams.value
Expand All @@ -30,11 +29,11 @@ export const useCollectionMeta = ({
params.source,
mediaType
)
return `${i18n.t(`collection.pageTitle.source.${mediaType}`, { source: sourceName })} | Openverse`
return `${t(`collection.pageTitle.source.${mediaType}`, { source: sourceName })} | Openverse`
}

if (params.collection === "tag") {
return `${i18n.t(`collection.pageTitle.tag.${mediaType}`, { tag: params.tag })} | Openverse`
return `${t(`collection.pageTitle.tag.${mediaType}`, { tag: params.tag })} | Openverse`
}
}

Expand Down
Loading

0 comments on commit 1cf820e

Please sign in to comment.