Skip to content

Commit

Permalink
feat: add support for route translations
Browse files Browse the repository at this point in the history
closes #50, refs #29
  • Loading branch information
Alexandre-Fernandez authored and yassinedoghri committed Nov 6, 2022
1 parent 7dcd0aa commit db5200b
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 7 deletions.
16 changes: 11 additions & 5 deletions src/cli/generate.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import fs from "fs";
import { AstroI18nextConfig } from "types";
import {
getAstroPagesPath,
createFiles,
FileToGenerate,
generateLocalizedFrontmatter,
overwriteAstroFrontmatter,
parseFrontmatter,
createTranslatedPath,
} from "./utils";

/**
Expand All @@ -17,8 +19,9 @@ import {
*/
export const generate = (
inputPath: string,
defaultLanguage: string,
supportedLanguages: string[],
defaultLanguage: AstroI18nextConfig["defaultLanguage"],
supportedLanguages: AstroI18nextConfig["supportedLanguages"],
routeTranslations?: AstroI18nextConfig["routes"],
outputPath: string = inputPath
): { filesToGenerate: FileToGenerate[]; timeToProcess: number } => {
const start = process.hrtime();
Expand Down Expand Up @@ -48,9 +51,12 @@ export const generate = (
);

filesToGenerate.push({
path: [outputPath, language === defaultLanguage ? null : language, file]
.filter(Boolean)
.join("/"),
path: createTranslatedPath(
file,
language === defaultLanguage ? undefined : language,
outputPath,
routeTranslations
),
source: newFileContents,
});
});
Expand Down
1 change: 1 addition & 0 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ yargs(hideBin(process.argv))
pagesPath,
argv.config.defaultLanguage,
argv.config.supportedLanguages,
argv.config.routes,
argv.output
);

Expand Down
25 changes: 25 additions & 0 deletions src/cli/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import path from "path";
import fs from "fs";
import ts from "typescript";
import { transformer } from "./transformer";
import { AstroI18nextConfig } from "types";

export interface FileToGenerate {
path: string;
Expand Down Expand Up @@ -139,4 +140,28 @@ export const createFiles = (filesToGenerate: FileToGenerate[]): void => {
fs.writeFileSync(fileToGenerate.path, fileToGenerate.source);
});
};

/**
* Translates `path` with `routeTranslations` if `lang` exists in
* `routeTranslations`, else returns `[basePath, path].join("/")` or
* `[basePath, language, path].join("/")`.
* @param basePath defaults to `""`.
*/
export const createTranslatedPath = (
path: string,
language?: string,
basePath = "",
routeTranslations: AstroI18nextConfig["routes"] = {}
) => {
if (!language) return `${basePath}/${path}`;
if (!routeTranslations[language]) return `${basePath}/${language}/${path}`;
return `${basePath}/${language}/${path
.split("/")
.map((segment) => {
const translated = routeTranslations[language][segment];
if (!translated) return segment;
return translated;
})
.join("/")}`;
};
/* c8 ignore stop */
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const I18NEXT_ROUTES_BUNDLE_NS = "astroI18nextConfig.routes";
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
moveBaseLanguageToFirstIndex,
deeplyStringifyObject,
getUserConfig,
createResourceBundleCallback,
} from "./utils";

export default (options?: AstroI18nextOptions): AstroIntegration => {
Expand Down Expand Up @@ -94,7 +95,7 @@ export default (options?: AstroI18nextOptions): AstroIntegration => {
}
i18nextInit += `.init(${deeplyStringifyObject(
astroI18nextConfig.i18next
)});`;
)}, ${createResourceBundleCallback(astroI18nextConfig.routes)});`;

injectScript("page-ssr", imports + i18nextInit);
},
Expand Down
9 changes: 9 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,13 @@ export interface AstroI18nextConfig {
i18nextPlugins?: {
[key: string]: string;
};

/**
* The translations for your routes.
*
* @default undefined
*/
routes: {
[language: string]: Record<string, string>;
};
}
27 changes: 26 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import i18next, { t } from "i18next";
import i18next, { type i18n, t } from "i18next";
import { fileURLToPath } from "url";
import load from "@proload/core";
import { AstroI18nextConfig } from "./types";
import typescript from "@proload/plugin-tsm";
import { I18NEXT_ROUTES_BUNDLE_NS } from "./constants";

/**
* Adapted from astro's tailwind integration:
Expand Down Expand Up @@ -150,6 +151,12 @@ export const localizePath = (
}
}

// translating pathSegments
const routeTranslations = getLanguageRouteTranslations(i18next, locale) || {};
pathSegments = pathSegments.map((segment) =>
routeTranslations[segment] ? routeTranslations[segment] : segment
);

// prepend the given locale if it's not the base one
if (locale !== i18next.options.supportedLngs[0]) {
pathSegments = [locale, ...pathSegments];
Expand Down Expand Up @@ -247,3 +254,21 @@ export const deeplyStringifyObject = (obj: object | Array<any>): string => {
}
return `${str}${isArray ? "]" : "}"}`;
};

export const createResourceBundleCallback = (
routes: AstroI18nextConfig["routes"] = {}
) => {
let callback = "() => {";
for (const lang in routes) {
callback += `i18next.addResourceBundle("${lang}", "${I18NEXT_ROUTES_BUNDLE_NS}", ${JSON.stringify(
routes[lang]
)});`;
}
return `${callback}}`;
};

export const getLanguageRouteTranslations = (i18next: i18n, lang: string) => {
return i18next.getResourceBundle(lang, I18NEXT_ROUTES_BUNDLE_NS) as
| AstroI18nextConfig["routes"][keyof AstroI18nextConfig["routes"]]
| undefined;
};

0 comments on commit db5200b

Please sign in to comment.