Skip to content

Commit

Permalink
createTranslator
Browse files Browse the repository at this point in the history
  • Loading branch information
KishiTheMechanic committed Oct 27, 2024
1 parent e5d7566 commit 27e8a46
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 34 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ file does not exist, it is skipped without an error, ensuring flexibility.

```tsx
import { define } from '@/utils/state.ts'
import { createTranslator } from 'jsr:@elsoul/fresh-i18n'

export const handler = define.handlers({
GET(ctx) {
Expand All @@ -151,9 +152,10 @@ export const handler = define.handlers({
})

export default define.page<typeof handler>(function Home(props) {
console.log('props', props.state.t('common.title')) // Access translation data using getTranslation function via props
const { t } = createTranslator(props.state.translationData)
return (
<div>
{t('common.title')} // Home or ホーム
</div>
)
})
Expand Down Expand Up @@ -196,7 +198,7 @@ export const stateAtom = atom<ExtendedState>({
ogImage: '',
noIndex: false,
locale: 'en',
t: {},
translationData: {},
path: '/',
})

Expand Down Expand Up @@ -231,7 +233,7 @@ export function useTranslation() {
*/
const t = (key: string): string => {
const keys = key.split('.')
let result: Record<string, unknown> | string = state.t
let result: Record<string, unknown> | string = state.translationData

for (const k of keys) {
if (typeof result === 'object' && result !== null && k in result) {
Expand Down
2 changes: 1 addition & 1 deletion deno.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@elsoul/fresh-i18n",
"version": "0.9.10",
"version": "0.9.11",
"description": "A simple and flexible internationalization (i18n) plugin for Deno's Fresh framework.",
"runtimes": ["deno", "browser"],
"exports": "./mod.ts",
Expand Down
1 change: 1 addition & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { i18nPlugin } from '@/src/i18nPlugin.ts'
export { createTranslator } from '@/src/createTranslator.ts'

export type { TranslationState } from '@/src/types.ts'
33 changes: 33 additions & 0 deletions src/createTranslator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* Retrieves a translation value from a nested translation object.
*
* @param translations - The translations object (e.g., ctx.state.translationData).
* @returns A function `t` that takes a translation key in dot notation and returns the translated string.
*/
export function createTranslator(
translations: Record<string, Record<string, string>>,
) {
/**
* Translates a key string like 'common.title' or 'common.titlerow.title.example'
* by traversing the nested structure of `translations`.
*
* @param key - The translation key in dot notation (e.g., 'common.title').
* @returns The translated string, or an empty string if the key is not found.
*/
const t = (key: string): string => {
const keys = key.split('.')
let result: unknown = translations

for (const k of keys) {
if (typeof result === 'object' && result !== null && k in result) {
result = (result as Record<string, unknown>)[k]
} else {
return '' // Return empty string if key is not found
}
}

return typeof result === 'string' ? result : ''
}

return t
}
28 changes: 0 additions & 28 deletions src/i18nPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,6 @@ async function readJsonFile(filePath: string): Promise<Record<string, string>> {
}
}

/**
* Retrieves a translation value from a nested translation object.
*
* @param translations - The translations object (e.g., ctx.state.translationData).
* @param key - The translation key in dot notation (e.g., 'common.title').
* @returns The translated string, or an empty string if the key is not found.
*/
function getTranslation(
translations: Record<string, unknown>,
key: string,
): string {
const keys = key.split('.')
let result: unknown = translations

for (const k of keys) {
if (typeof result === 'object' && result !== null && k in result) {
result = (result as Record<string, unknown>)[k]
} else {
return '' // Return empty string if key is not found
}
}

return typeof result === 'string' ? result : ''
}

/**
* Middleware function to initialize internationalization (i18n) support.
* This plugin detects the user's language based on the URL, loads the necessary
Expand Down Expand Up @@ -105,10 +80,7 @@ export const i18nPlugin = (
await loadTranslation(segment)
}

// Set translationData and t function in ctx.state
ctx.state.translationData = translationData
ctx.state.t = (key: string) =>
getTranslation(ctx.state.translationData, key)

const response = await ctx.next() as Response
return response
Expand Down
2 changes: 0 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@
* @property translationData - Object holding translation data for different namespaces.
* @property path - The base path of the URL without the language prefix.
* @property locale - The current locale code, used for translations.
* @property t - A function to get a translated string by key in dot notation.
*/
export interface TranslationState {
translationData: Record<string, Record<string, string>>
path: string
locale: string
t: (key: string) => string // Function to retrieve translation string
}

/**
Expand Down

0 comments on commit 27e8a46

Please sign in to comment.