-
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from aypineau/feat-implement-i18n-outpout
feat: implement i18n output
- Loading branch information
Showing
21 changed files
with
375 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
...idar/src/transpiler/declaration_file_to_dictionary/i18n_dictionary/buildI18nDictionary.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { mkdir, writeFile } from 'fs/promises'; | ||
import { resolve } from 'path'; | ||
import { getConfiguration } from '@intlayer/config'; | ||
import type { ContentModule } from '@intlayer/core'; | ||
import { | ||
processContentDeclaration, | ||
extractObjectsWithId, | ||
} from '../intlayer_dictionary/index'; | ||
import { | ||
type I18nDictionariesOutput, | ||
createI18nDictionaries, | ||
} from './convertContentDeclarationInto18nDictionaries'; | ||
|
||
const { content } = getConfiguration(); | ||
const { i18nDictionariesDir } = content; | ||
|
||
type DictionariesDeclaration = Record<string, I18nDictionariesOutput>; | ||
|
||
/** | ||
* This function writes the dictionaries to the file system | ||
*/ | ||
const writeDictionary = async ( | ||
dictionariesDeclaration: DictionariesDeclaration | ||
) => { | ||
const resultDictionariesPaths: string[] = []; | ||
|
||
for (const [nameSpace, localContent] of Object.entries( | ||
dictionariesDeclaration | ||
)) { | ||
for await (const [locale, content] of Object.entries(localContent)) { | ||
const contentString = JSON.stringify(content); | ||
|
||
const outputFileName = `${nameSpace}.json`; | ||
const resultDirPath = resolve(i18nDictionariesDir, locale); | ||
const resultFilePath = resolve(resultDirPath, outputFileName); | ||
|
||
// Create the dictionaries folder if it doesn't exist | ||
await mkdir(resultDirPath, { recursive: true }); | ||
|
||
// Create the json file | ||
await writeFile(resultFilePath, contentString, 'utf8').catch((err) => { | ||
console.error(`Error creating ${outputFileName}:`, err); | ||
}); | ||
|
||
resultDictionariesPaths.push(resultFilePath); | ||
} | ||
} | ||
|
||
return resultDictionariesPaths; | ||
}; | ||
|
||
/** | ||
* This function transpile content declaration to i18n dictionaries | ||
*/ | ||
export const buildI18nDictionary = async ( | ||
contentDeclarationsPaths: string[] | string | ||
) => { | ||
const resultDictionariesPaths: string[] = []; | ||
|
||
if (typeof contentDeclarationsPaths === 'string') { | ||
contentDeclarationsPaths = [contentDeclarationsPaths]; | ||
} | ||
|
||
for await (const contentDeclarationPath of contentDeclarationsPaths) { | ||
const result = await processContentDeclaration(contentDeclarationPath); | ||
|
||
if (!result) { | ||
continue; | ||
} | ||
|
||
const nestedContent: ContentModule[] = extractObjectsWithId(result); | ||
|
||
// Create dictionaries for each nested content and format them | ||
const dictionariesDeclaration: DictionariesDeclaration = | ||
nestedContent.reduce((acc, content) => { | ||
const id = content.id; | ||
const i18Content = createI18nDictionaries(content); | ||
|
||
return { | ||
...acc, | ||
[id]: i18Content, | ||
}; | ||
}, {}); | ||
|
||
// Write the dictionaries to the file system | ||
const dictionariesPaths: string[] = await writeDictionary( | ||
dictionariesDeclaration | ||
); | ||
|
||
// Add the paths to the result | ||
resultDictionariesPaths.push(...dictionariesPaths); | ||
} | ||
|
||
return resultDictionariesPaths; | ||
}; |
91 changes: 91 additions & 0 deletions
91
...ration_file_to_dictionary/i18n_dictionary/convertContentDeclarationInto18nDictionaries.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import { getConfiguration, type Locales } from '@intlayer/config'; | ||
import { | ||
NodeType, | ||
type TranslationContent, | ||
type Content, | ||
type TypedNode, | ||
type EnumerationContent, | ||
} from '@intlayer/core'; | ||
import { convertPluralsValues } from './convertPluralsValues'; | ||
|
||
type Dictionary = Record<string, unknown>; | ||
export type I18nDictionariesOutput = Partial<Record<Locales, Dictionary>>; | ||
|
||
const { | ||
internationalization: { locales }, | ||
} = getConfiguration(); | ||
|
||
const isReactNode = (node: Record<string, unknown>): boolean => | ||
typeof node?.key !== 'undefined' && | ||
typeof node?.props !== 'undefined' && | ||
typeof node?.type !== 'undefined'; | ||
|
||
// Build dictionary for a specific locale | ||
const buildDictionary = (content: Dictionary, locale: Locales): unknown => { | ||
if ( | ||
// Translation node | ||
content && | ||
(content as TypedNode).nodeType === NodeType.Translation | ||
) { | ||
const result = (content as TranslationContent<unknown>)[locale]; | ||
|
||
return buildDictionary(result as Dictionary, locale); | ||
} else if ( | ||
// Translation node | ||
content && | ||
(content as TypedNode).nodeType === NodeType.Enumeration | ||
) { | ||
const plurals: Record<string, unknown> = {}; | ||
|
||
Object.keys(content).forEach((quantity) => { | ||
const letterNumber = convertPluralsValues(quantity); | ||
|
||
const value = (content as EnumerationContent<unknown>)[ | ||
quantity as keyof EnumerationContent<unknown> | ||
]; | ||
|
||
plurals[`${letterNumber}_${letterNumber}`] = buildDictionary( | ||
value as Dictionary, | ||
locale | ||
); | ||
}); | ||
|
||
return plurals; | ||
} else if ( | ||
// React element node | ||
isReactNode(content as Record<string, unknown>) | ||
) { | ||
return JSON.stringify(content); | ||
} else if ( | ||
// Nested object | ||
typeof content === 'object' | ||
) { | ||
const result: Record<string, unknown> = {}; | ||
|
||
Object.keys(content).forEach((dictionaryValue) => { | ||
result[dictionaryValue] = buildDictionary( | ||
content[dictionaryValue] as Dictionary, | ||
locale | ||
); | ||
}); | ||
|
||
return result; | ||
} | ||
|
||
return content; | ||
}; | ||
|
||
export const createI18nDictionaries = ( | ||
content: Content | ||
): I18nDictionariesOutput => { | ||
// Map dictionaries for each locale | ||
const result: I18nDictionariesOutput = locales.reduce( | ||
(acc, locale) => ({ | ||
...acc, | ||
[locale]: buildDictionary(content, locale), | ||
}), | ||
{} | ||
); | ||
|
||
return result; | ||
}; |
22 changes: 22 additions & 0 deletions
22
...dar/src/transpiler/declaration_file_to_dictionary/i18n_dictionary/convertPluralsValues.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
export const convertPluralsValues = (number: string): string => { | ||
switch (number) { | ||
case '1': | ||
return 'one'; | ||
case '2': | ||
return 'two'; | ||
case '3': | ||
return 'three'; | ||
case '4': | ||
return 'four'; | ||
case '5': | ||
return 'five'; | ||
case '6': | ||
return 'six'; | ||
case '7': | ||
return 'seven'; | ||
case '8': | ||
return 'eight'; | ||
default: | ||
return number.toString(); | ||
} | ||
}; |
1 change: 1 addition & 0 deletions
1
...@intlayer/chokidar/src/transpiler/declaration_file_to_dictionary/i18n_dictionary/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './buildI18nDictionary'; |
21 changes: 21 additions & 0 deletions
21
packages/@intlayer/chokidar/src/transpiler/declaration_file_to_dictionary/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { getConfiguration } from '@intlayer/config'; | ||
import { buildI18nDictionary } from './i18n_dictionary/index'; | ||
import { buildIntlayerDictionary } from './intlayer_dictionary/index'; | ||
|
||
const { | ||
content: { dictionaryOutput }, | ||
} = getConfiguration(); | ||
|
||
export const buildDictionary = async ( | ||
contentDeclarationsPaths: string | string[] | ||
): Promise<string[]> => { | ||
if (dictionaryOutput.includes('i18next')) { | ||
return await buildI18nDictionary(contentDeclarationsPaths); | ||
} | ||
|
||
if (dictionaryOutput.includes('intlayer')) { | ||
return await buildIntlayerDictionary(contentDeclarationsPaths); | ||
} | ||
|
||
return []; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
3 changes: 3 additions & 0 deletions
3
...layer/chokidar/src/transpiler/declaration_file_to_dictionary/intlayer_dictionary/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from './extractNestedJSON'; | ||
export * from './processContentDeclaration'; | ||
export * from './buildIntlayerDictionary'; |
File renamed without changes.
File renamed without changes.
3 changes: 0 additions & 3 deletions
3
packages/@intlayer/chokidar/src/transpiler/intlater_module_to_dictionary/index.ts
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.