mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-24 23:31:30 +00:00
I18 quality of life change (#973)
* I18 quality of life change * Cleanup
This commit is contained in:
parent
16cb506147
commit
e947549cdc
|
@ -30,30 +30,70 @@ fs.readdir(translationDir, (_err, files) => {
|
|||
const baseLanguage = "en";
|
||||
|
||||
fs.readFile(`${translationDir}${baseLanguage}.json`, "utf8", (_, fileStr) => {
|
||||
const keys = Object.keys(JSON.parse(fileStr));
|
||||
const noOptionKeys = [];
|
||||
const optionKeys = [];
|
||||
const optionRegex = /\{\{(.+?)\}\}/g;
|
||||
const optionMap = new Map();
|
||||
|
||||
for (const [key, val] of Object.entries(JSON.parse(fileStr))) {
|
||||
const options = [];
|
||||
for (
|
||||
let match = optionRegex.exec(val);
|
||||
match;
|
||||
match = optionRegex.exec(val)
|
||||
) {
|
||||
options.push(match[1]);
|
||||
}
|
||||
|
||||
if (options.length > 0) {
|
||||
optionMap.set(key, options);
|
||||
optionKeys.push(key);
|
||||
} else {
|
||||
noOptionKeys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
const indent = " ";
|
||||
|
||||
const data = `import { i18n } from "i18next";
|
||||
|
||||
declare module "i18next" {
|
||||
export type I18nKeys =
|
||||
${keys.map(key => ` | "${key}"`).join("\n")};
|
||||
export type NoOptionI18nKeys =
|
||||
${noOptionKeys.map(key => `${indent}| "${key}"`).join("\n")};
|
||||
|
||||
export type OptionI18nKeys =
|
||||
${optionKeys.map(key => `${indent}| "${key}"`).join("\n")};
|
||||
|
||||
export type I18nKeys = NoOptionI18nKeys | OptionI18nKeys;
|
||||
|
||||
export type TTypedOptions<TKey extends OptionI18nKeys> =${Array.from(
|
||||
optionMap.entries()
|
||||
).reduce(
|
||||
(acc, [key, options]) =>
|
||||
`${acc} TKey extends \"${key}\" ? ${
|
||||
options.reduce((acc, cur) => acc + `${cur}: string | number; `, "{ ") +
|
||||
"}"
|
||||
} :\n${indent}`,
|
||||
""
|
||||
)} (Record<string, unknown> | string);
|
||||
|
||||
export interface TFunctionTyped {
|
||||
// basic usage
|
||||
// Translation requires options
|
||||
<
|
||||
TKey extends OptionI18nKeys | OptionI18nKeys[],
|
||||
TResult extends TFunctionResult = string,
|
||||
TInterpolationMap extends Record<string, unknown> = StringMap
|
||||
TInterpolationMap extends TTypedOptions<TKey> = StringMap
|
||||
> (
|
||||
key: I18nKeys | I18nKeys[],
|
||||
options?: TOptions<TInterpolationMap> | string
|
||||
key: TKey,
|
||||
options: TOptions<TInterpolationMap> | string
|
||||
): TResult;
|
||||
// overloaded usage
|
||||
|
||||
// Translation does not require options
|
||||
<
|
||||
TResult extends TFunctionResult = string,
|
||||
TInterpolationMap extends Record<string, unknown> = StringMap
|
||||
> (
|
||||
key: I18nKeys | I18nKeys[],
|
||||
defaultValue?: string,
|
||||
key: NoOptionI18nKeys | NoOptionI18nKeys[],
|
||||
options?: TOptions<TInterpolationMap> | string
|
||||
): TResult;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { I18nKeys } from "i18next";
|
||||
import { NoOptionI18nKeys } from "i18next";
|
||||
import { Component } from "inferno";
|
||||
import { i18n } from "../../i18next";
|
||||
|
||||
export class NoMatch extends Component<any, any> {
|
||||
private errCode = new URLSearchParams(this.props.location.search).get(
|
||||
"err"
|
||||
) as I18nKeys;
|
||||
) as NoOptionI18nKeys;
|
||||
|
||||
constructor(props: any, context: any) {
|
||||
super(props, context);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Options, passwordStrength } from "check-password-strength";
|
||||
import { I18nKeys } from "i18next";
|
||||
import { NoOptionI18nKeys } from "i18next";
|
||||
import { Component, linkEvent } from "inferno";
|
||||
import { T } from "inferno-i18next-dess";
|
||||
import {
|
||||
|
@ -231,7 +231,7 @@ export class Signup extends Component<any, State> {
|
|||
/>
|
||||
{this.state.form.password && (
|
||||
<div className={this.passwordColorClass}>
|
||||
{i18n.t(this.passwordStrength as I18nKeys)}
|
||||
{i18n.t(this.passwordStrength as NoOptionI18nKeys)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue