Incorporate i18n into UI elements (#1471)

* Update zh-tw string table (till 975343d2)
* Prepare localization table
* Implement i18n for Performers & Tags
* Add "add" action strings
* Use Lodash merge for deep merging language JSONs

The original implementation does not properly merge language files, causing unexpected localization string fallback behavior.

* Localize pagination strings
* Use Field name value as null id fallback

...otherwise FormattedMessage is gonna throw when the ID is null

* Use localized "Path" string for all instances
* Localize the "Interface" tab under settings
* Localize scene & performer cards
* Rename locale folder for better compatibility with i18n-ally
* Localize majority of the categories and features
This commit is contained in:
Still Hsu
2021-06-14 14:48:59 +09:00
committed by GitHub
parent 46bbede9a0
commit 3ae187e6f0
105 changed files with 3441 additions and 1084 deletions

View File

@@ -4,7 +4,7 @@ import { useScenesDestroy } from "src/core/StashService";
import * as GQL from "src/core/generated-graphql";
import { Modal } from "src/components/Shared";
import { useToast } from "src/hooks";
import { FormattedMessage } from "react-intl";
import { useIntl } from "react-intl";
interface IDeleteSceneDialogProps {
selected: GQL.SlimSceneDataFragment[];
@@ -14,20 +14,22 @@ interface IDeleteSceneDialogProps {
export const DeleteScenesDialog: React.FC<IDeleteSceneDialogProps> = (
props: IDeleteSceneDialogProps
) => {
const plural = props.selected.length > 1;
const intl = useIntl();
const singularEntity = intl.formatMessage({ id: "scene" });
const pluralEntity = intl.formatMessage({ id: "scenes" });
const singleMessageId = "deleteSceneText";
const pluralMessageId = "deleteScenesText";
const singleMessage =
"Are you sure you want to delete this scene? Unless the file is also deleted, this scene will be re-added when scan is performed.";
const pluralMessage =
"Are you sure you want to delete these scenes? Unless the files are also deleted, these scenes will be re-added when scan is performed.";
const header = plural ? "Delete Scenes" : "Delete Scene";
const toastMessage = plural ? "Deleted scenes" : "Deleted scene";
const messageId = plural ? pluralMessageId : singleMessageId;
const message = plural ? pluralMessage : singleMessage;
const header = intl.formatMessage(
{ id: "dialogs.delete_entity_title" },
{ count: props.selected.length, singularEntity, pluralEntity }
);
const toastMessage = intl.formatMessage(
{ id: "toast.delete_entity" },
{ count: props.selected.length, singularEntity, pluralEntity }
);
const message = intl.formatMessage(
{ id: "dialogs.delete_entity_desc" },
{ count: props.selected.length, singularEntity, pluralEntity }
);
const [deleteFile, setDeleteFile] = useState<boolean>(false);
const [deleteGenerated, setDeleteGenerated] = useState<boolean>(true);
@@ -63,28 +65,32 @@ export const DeleteScenesDialog: React.FC<IDeleteSceneDialogProps> = (
show
icon="trash-alt"
header={header}
accept={{ variant: "danger", onClick: onDelete, text: "Delete" }}
accept={{
variant: "danger",
onClick: onDelete,
text: intl.formatMessage({ id: "actions.delete" }),
}}
cancel={{
onClick: () => props.onClose(false),
text: "Cancel",
text: intl.formatMessage({ id: "actions.cancel" }),
variant: "secondary",
}}
isRunning={isDeleting}
>
<p>
<FormattedMessage id={messageId} defaultMessage={message} />
</p>
<p>{message}</p>
<Form>
<Form.Check
id="delete-file"
checked={deleteFile}
label="Delete file"
label={intl.formatMessage({ id: "actions.delete_file" })}
onChange={() => setDeleteFile(!deleteFile)}
/>
<Form.Check
id="delete-generated"
checked={deleteGenerated}
label="Delete generated supporting files"
label={intl.formatMessage({
id: "actions.delete_generated_supporting_files",
})}
onChange={() => setDeleteGenerated(!deleteGenerated)}
/>
</Form>