mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-29 15:51:14 +00:00
I18 quality of life change (#973)
* I18 quality of life change * Cleanup
This commit is contained in:
parent
9e58f6550d
commit
70f285fa20
3 changed files with 57 additions and 17 deletions
|
@ -30,30 +30,70 @@ fs.readdir(translationDir, (_err, files) => {
|
||||||
const baseLanguage = "en";
|
const baseLanguage = "en";
|
||||||
|
|
||||||
fs.readFile(`${translationDir}${baseLanguage}.json`, "utf8", (_, fileStr) => {
|
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";
|
const data = `import { i18n } from "i18next";
|
||||||
|
|
||||||
declare module "i18next" {
|
declare module "i18next" {
|
||||||
export type I18nKeys =
|
export type NoOptionI18nKeys =
|
||||||
${keys.map(key => ` | "${key}"`).join("\n")};
|
${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 {
|
export interface TFunctionTyped {
|
||||||
// basic usage
|
// Translation requires options
|
||||||
<
|
<
|
||||||
|
TKey extends OptionI18nKeys | OptionI18nKeys[],
|
||||||
TResult extends TFunctionResult = string,
|
TResult extends TFunctionResult = string,
|
||||||
TInterpolationMap extends Record<string, unknown> = StringMap
|
TInterpolationMap extends TTypedOptions<TKey> = StringMap
|
||||||
>(
|
> (
|
||||||
key: I18nKeys | I18nKeys[],
|
key: TKey,
|
||||||
options?: TOptions<TInterpolationMap> | string
|
options: TOptions<TInterpolationMap> | string
|
||||||
): TResult;
|
): TResult;
|
||||||
// overloaded usage
|
|
||||||
|
// Translation does not require options
|
||||||
<
|
<
|
||||||
TResult extends TFunctionResult = string,
|
TResult extends TFunctionResult = string,
|
||||||
TInterpolationMap extends Record<string, unknown> = StringMap
|
TInterpolationMap extends Record<string, unknown> = StringMap
|
||||||
>(
|
> (
|
||||||
key: I18nKeys | I18nKeys[],
|
key: NoOptionI18nKeys | NoOptionI18nKeys[],
|
||||||
defaultValue?: string,
|
|
||||||
options?: TOptions<TInterpolationMap> | string
|
options?: TOptions<TInterpolationMap> | string
|
||||||
): TResult;
|
): TResult;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { I18nKeys } from "i18next";
|
import { NoOptionI18nKeys } from "i18next";
|
||||||
import { Component } from "inferno";
|
import { Component } from "inferno";
|
||||||
import { i18n } from "../../i18next";
|
import { i18n } from "../../i18next";
|
||||||
|
|
||||||
export class NoMatch extends Component<any, any> {
|
export class NoMatch extends Component<any, any> {
|
||||||
private errCode = new URLSearchParams(this.props.location.search).get(
|
private errCode = new URLSearchParams(this.props.location.search).get(
|
||||||
"err"
|
"err"
|
||||||
) as I18nKeys;
|
) as NoOptionI18nKeys;
|
||||||
|
|
||||||
constructor(props: any, context: any) {
|
constructor(props: any, context: any) {
|
||||||
super(props, context);
|
super(props, context);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Options, passwordStrength } from "check-password-strength";
|
import { Options, passwordStrength } from "check-password-strength";
|
||||||
import { I18nKeys } from "i18next";
|
import { NoOptionI18nKeys } from "i18next";
|
||||||
import { Component, linkEvent } from "inferno";
|
import { Component, linkEvent } from "inferno";
|
||||||
import { T } from "inferno-i18next-dess";
|
import { T } from "inferno-i18next-dess";
|
||||||
import {
|
import {
|
||||||
|
@ -231,7 +231,7 @@ export class Signup extends Component<any, State> {
|
||||||
/>
|
/>
|
||||||
{this.state.form.password && (
|
{this.state.form.password && (
|
||||||
<div className={this.passwordColorClass}>
|
<div className={this.passwordColorClass}>
|
||||||
{i18n.t(this.passwordStrength as I18nKeys)}
|
{i18n.t(this.passwordStrength as NoOptionI18nKeys)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue