From e76a417f318f8d093a20e45656bf443e81afd8d5 Mon Sep 17 00:00:00 2001 From: PhilReact Date: Wed, 21 May 2025 00:35:39 +0300 Subject: [PATCH] added languages --- src/components/RegisterName.tsx | 20 +- src/components/Tables/ForSaleTable.tsx | 47 +++- src/components/Tables/NameTable.tsx | 292 +++++++++++++++++++------ src/i18n/locales/de/core.json | 96 ++++++++ src/i18n/locales/en/core.json | 76 ++++++- src/i18n/locales/es/core.json | 92 +++++++- src/i18n/locales/fr/core.json | 96 ++++++++ src/i18n/locales/it/core.json | 96 ++++++++ src/i18n/locales/ru/core.json | 96 ++++++++ src/pages/Market.tsx | 2 +- src/pages/MyNames.tsx | 2 +- src/styles/Layout.tsx | 4 +- 12 files changed, 825 insertions(+), 94 deletions(-) create mode 100644 src/i18n/locales/de/core.json create mode 100644 src/i18n/locales/fr/core.json create mode 100644 src/i18n/locales/it/core.json create mode 100644 src/i18n/locales/ru/core.json diff --git a/src/components/RegisterName.tsx b/src/components/RegisterName.tsx index 5e50df4..af5a7e9 100644 --- a/src/components/RegisterName.tsx +++ b/src/components/RegisterName.tsx @@ -82,7 +82,7 @@ const RegisterName = () => { if (!address) return; const loadId = showLoading( t('core:new_name.responses.loading', { - postProcess: 'capitalize', + postProcess: 'capitalizeFirstChar', }) ); try { @@ -114,7 +114,7 @@ const RegisterName = () => { }); showSuccess( t('core:new_name.responses.success', { - postProcess: 'capitalize', + postProcess: 'capitalizeFirstChar', }) ); setNameValue(''); @@ -125,7 +125,7 @@ const RegisterName = () => { } else { showError( t('core:new_name.responses.error', { - postProcess: 'capitalize', + postProcess: 'capitalizeFirstChar', }) ); } @@ -191,7 +191,7 @@ const RegisterName = () => { }} > {t('core:actions.new_name', { - postProcess: 'capitalize', + postProcess: 'capitalizeFirstChar', })} { > {t('core:actions.register_name', { - postProcess: 'capitalize', + postProcess: 'capitalizeFirstChar', })} @@ -225,7 +225,7 @@ const RegisterName = () => { onChange={(e) => setNameValue(e.target.value)} value={nameValue} placeholder={t('core:new_name.choose_name', { - postProcess: 'capitalize', + postProcess: 'capitalizeFirstChar', })} /> {(!balance || (nameFee && balance && balance < nameFee)) && ( @@ -247,7 +247,7 @@ const RegisterName = () => { {t('balance_message', { balance: balance ?? 0, nameFee, - postProcess: 'capitalize', + postProcess: 'capitalizeFirstChar', })} @@ -302,7 +302,7 @@ const RegisterName = () => { {t('core:new_name.checking_name', { - postProcess: 'capitalize', + postProcess: 'capitalizeFirstChar', })} @@ -319,7 +319,7 @@ const RegisterName = () => { }} > {t('core:actions.close', { - postProcess: 'capitalize', + postProcess: 'capitalizeFirstChar', })} diff --git a/src/components/Tables/ForSaleTable.tsx b/src/components/Tables/ForSaleTable.tsx index d51556e..3e22014 100644 --- a/src/components/Tables/ForSaleTable.tsx +++ b/src/components/Tables/ForSaleTable.tsx @@ -24,6 +24,8 @@ import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward'; import { dismissToast, showError, showLoading, showSuccess } from 'qapp-core'; import { SetStateAction } from 'jotai'; import { SortBy, SortDirection } from '../../interfaces'; +import { useTranslation } from 'react-i18next'; +import { TFunction } from 'i18next'; const VirtuosoTableComponents: TableComponents = { Scroller: forwardRef((props, ref) => ( @@ -47,7 +49,8 @@ const VirtuosoTableComponents: TableComponents = { function fixedHeaderContent( sortBy: string, sortDirection: string, - setSort: (field: SortBy) => void + setSort: (field: SortBy) => void, + t: TFunction ) { const renderSortIcon = (field: string) => { if (sortBy !== field) return null; @@ -70,12 +73,18 @@ function fixedHeaderContent( setSort('name')} sx={sortableCellSx}> - Name {renderSortIcon('name')} + {t('core:tables.name', { + postProcess: 'capitalizeFirstChar', + })} + {renderSortIcon('name')} setSort('salePrice')} sx={sortableCellSx}> - Sale Price {renderSortIcon('salePrice')} + {t('core:market.sale_price', { + postProcess: 'capitalizeFirstChar', + })}{' '} + {renderSortIcon('salePrice')} Actions @@ -95,17 +104,26 @@ function rowContent( setPendingTxs: SetPendingTxs, setNames: SetNames, setNamesForSale: SetNamesForSale, - isPrimaryNameForSale: boolean + isPrimaryNameForSale: boolean, + t: TFunction ) { const handleBuy = async (name: string) => { - const loadId = showLoading('Attempting to purchase name...please wait'); + const loadId = showLoading( + t('core:market.responses.loading', { + postProcess: 'capitalizeFirstChar', + }) + ); try { const res = await qortalRequest({ action: 'BUY_NAME', nameForSale: name, }); - showSuccess('Purchased name'); + showSuccess( + t('core:market.responses.success', { + postProcess: 'capitalizeFirstChar', + }) + ); setPendingTxs((prev) => { return { ...prev, // preserve existing categories @@ -135,7 +153,11 @@ function rowContent( showError(error?.message); return; } - showError('Unable to purchase name'); + showError( + t('core:market.responses.error', { + postProcess: 'capitalizeFirstChar', + }) + ); } finally { dismissToast(loadId); } @@ -152,7 +174,9 @@ function rowContent( size="small" onClick={() => handleBuy(row.name)} > - Buy + {t('core:actions.buy', { + postProcess: 'capitalizeFirstChar', + })} @@ -177,7 +201,7 @@ export const ForSaleTable = ({ const setNames = useSetAtom(namesAtom); const setNamesForSale = useSetAtom(forSaleAtom); const setPendingTxs = useSetAtom(pendingTxsAtom); - + const { t } = useTranslation(); return ( - fixedHeaderContent(sortBy, sortDirection, handleSort) + fixedHeaderContent(sortBy, sortDirection, handleSort, t) } itemContent={(index, row: NamesForSale) => rowContent( @@ -198,7 +222,8 @@ export const ForSaleTable = ({ setPendingTxs, setNames, setNamesForSale, - isPrimaryNameForSale + isPrimaryNameForSale, + t ) } /> diff --git a/src/components/Tables/NameTable.tsx b/src/components/Tables/NameTable.tsx index 30bd98a..cf7be24 100644 --- a/src/components/Tables/NameTable.tsx +++ b/src/components/Tables/NameTable.tsx @@ -58,6 +58,8 @@ import { usePendingTxs } from '../../hooks/useHandlePendingTxs'; import { FetchPrimaryNameType, useFetchNames } from '../../hooks/useFetchNames'; import { Availability } from '../../interfaces'; import { SetStateAction } from 'jotai'; +import { useTranslation } from 'react-i18next'; +import { TFunction } from 'i18next'; interface NameData { name: string; isSelling?: boolean; @@ -84,15 +86,23 @@ const VirtuosoTableComponents: TableComponents = { )), }; -function fixedHeaderContent() { +function fixedHeaderContent(t: TFunction) { return ( - Name - Actions + + {t('core:tables.name', { + postProcess: 'capitalizeFirstChar', + })} + + + {t('core:tables.actions', { + postProcess: 'capitalizeFirstChar', + })} + ); } @@ -111,7 +121,7 @@ const ManageAvatar = ({ const { setHasAvatar, getHasAvatar } = usePendingTxs(); const [refresh] = useAtom(refreshAtom); // just to subscribe const [hasAvatarState, setHasAvatarState] = useState(null); - + const { t } = useTranslation(); const checkIfAvatarExists = useCallback( async (name: string) => { try { @@ -160,9 +170,13 @@ const ManageAvatar = ({ {hasAvatarState === null ? ( ) : hasAvatarState ? ( - 'Change avatar' + t('core:actions.update_avatar', { + postProcess: 'capitalizeFirstChar', + }) ) : ( - 'Set avatar' + t('core:actions.set_avatar', { + postProcess: 'capitalizeFirstChar', + }) )} ); @@ -186,14 +200,23 @@ function rowContent( setPendingTxs: SetPendingTxs, setNames: SetNames, setNamesForSale: SetNamesForSale, - isNameCurrentlyDoingATx: boolean + isNameCurrentlyDoingATx: boolean, + t: TFunction ) { const handleUpdate = async (name: string) => { if (name === primaryName && numberOfNames > 1) { - showError('Cannot update primary name while having other names'); + showError( + t('core:actions.set_avatar', { + postProcess: 'capitalizeFirstChar', + }) + ); return; } - const loadId = showLoading('Updating name...please wait'); + const loadId = showLoading( + t('core:update_name.responses.loading', { + postProcess: 'capitalizeFirstChar', + }) + ); try { const response = await modalFunctionsUpdateName.show(undefined); @@ -203,7 +226,11 @@ function rowContent( newName: response, oldName: name, }); - showSuccess('Successfully updated name'); + showSuccess( + t('core:update_name.responses.loading', { + postProcess: 'capitalizeFirstChar', + }) + ); setPendingTxs((prev) => { return { ...prev, // preserve existing categories @@ -236,7 +263,11 @@ function rowContent( showError(error?.message); return; } - showError('Unable to update name'); + showError( + t('core:update_name.responses.loading', { + postProcess: 'capitalizeFirstChar', + }) + ); console.log('error', error); } finally { dismissToast(loadId); @@ -247,23 +278,39 @@ function rowContent( const handleSell = async (name: string) => { if (name === primaryName && numberOfNames > 1) { - showError('Cannot sell primary name while having other names'); + showError( + t('core:sell_name.responses.error1', { + postProcess: 'capitalizeFirstChar', + }) + ); return; } - const loadId = showLoading('Placing name for sale...please wait'); + const loadId = showLoading( + t('core:sell_name.responses.loading', { + postProcess: 'capitalizeFirstChar', + }) + ); try { if (name === primaryName) { await modalFunctions.show({ name }); } const price = await modalFunctionsSellName.show(name); if (typeof price !== 'string' && typeof price !== 'number') - throw new Error('Invalid price'); + throw new Error( + t('core:sell_name.responses.error3', { + postProcess: 'capitalizeFirstChar', + }) + ); const res = await qortalRequest({ action: 'SELL_NAME', nameForSale: name, salePrice: +price, }); - showSuccess('Placed name for sale'); + showSuccess( + t('core:sell_name.responses.success', { + postProcess: 'capitalizeFirstChar', + }) + ); setPendingTxs((prev) => { return { ...prev, // preserve existing categories @@ -293,7 +340,11 @@ function rowContent( return; } - showError('Unable to place name for sale'); + showError( + t('core:sell_name.responses.error2', { + postProcess: 'capitalizeFirstChar', + }) + ); console.log('error', error); } finally { dismissToast(loadId); @@ -301,7 +352,11 @@ function rowContent( }; const handleCancel = async (name: string) => { - const loadId = showLoading('Removing name from market...please wait'); + const loadId = showLoading( + t('core:cancel_name.responses.error2', { + postProcess: 'capitalizeFirstChar', + }) + ); try { const res = await qortalRequest({ @@ -321,18 +376,25 @@ function rowContent( prev.filter((item) => item?.name !== res.name) ); }, - }, // add or overwrite this transaction + }, }, }; }); - showSuccess('Removed name from market'); + showSuccess( + t('core:cancel_name.responses.error2', { + postProcess: 'capitalizeFirstChar', + }) + ); } catch (error) { if (error instanceof Error) { showError(error?.message); return; } - showError('Unable to remove name from market'); - console.log('error', error); + showError( + t('core:cancel_name.responses.error2', { + postProcess: 'capitalizeFirstChar', + }) + ); } finally { dismissToast(loadId); } @@ -350,7 +412,9 @@ function rowContent( > {primaryName === row.name && ( handleUpdate(row.name)} > - Update + {t('core:actions.update', { + postProcess: 'capitalizeFirstChar', + })} {!row.isSelling ? ( ) : ( )} { const { auth } = useGlobal(); const [namesForSale, setNamesForSale] = useAtom(forSaleAtom); const [pendingTxs] = useAtom(pendingTxsAtom); + const { t } = useTranslation(['core']); const modalFunctions = useModal<{ name: string }>(); const modalFunctionsUpdateName = useModal(); @@ -453,7 +524,7 @@ export const NameTable = ({ names, primaryName }: NameTableProps) => { fixedHeaderContent(t)} itemContent={(index, row) => { const isNameCurrentlyDoingATx = isNamePendingTx( row?.name, @@ -473,7 +544,8 @@ export const NameTable = ({ names, primaryName }: NameTableProps) => { setPendingTxs, setNames, setNamesForSale, - isNameCurrentlyDoingATx + isNameCurrentlyDoingATx, + t ); }} /> @@ -483,17 +555,22 @@ export const NameTable = ({ names, primaryName }: NameTableProps) => { aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" > - Warning + + {t('core:warnings.warning', { + postProcess: 'capitalizeFirstChar', + })} + - Caution when selling your primary name + {t('core:warnings.primary_name_sell_caution', { + postProcess: 'capitalizeFirstChar', + })} - {modalFunctions?.data?.name} is your primary name. If you are an - admin of a private group, selling this name will remove your group - keys for the group. Make sure another admin re-encrypts the latest - keys before selling. Proceed with caution! + {t('core:warnings.primary_name_sell', { + name: modalFunctions?.data?.name, + })} @@ -503,10 +580,14 @@ export const NameTable = ({ names, primaryName }: NameTableProps) => { onClick={() => modalFunctions.onOk(undefined)} autoFocus > - continue + {t('core:actions.continue', { + postProcess: 'capitalizeFirstChar', + })} @@ -533,6 +614,7 @@ interface AvatarModalProps { modalFunctionsAvatar: ModalFunctionsAvatar; } const AvatarModal = ({ modalFunctionsAvatar }: AvatarModalProps) => { + const { t } = useTranslation(); const { setHasAvatar } = usePendingTxs(); const forceRefresh = useSetAtom(forceRefreshAtom); @@ -540,10 +622,18 @@ const AvatarModal = ({ modalFunctionsAvatar }: AvatarModalProps) => { const [isLoadingPublish, setIsLoadingPublish] = useState(false); const publishAvatar = async () => { - const loadId = showLoading('Publishing avatar...please wait'); + const loadId = showLoading( + t('core:avatar.responses.loading', { + postProcess: 'capitalizeFirstChar', + }) + ); try { if (!modalFunctionsAvatar?.data || !pickedAvatar?.base64) - throw new Error('Missing data'); + throw new Error( + t('core:avatar.responses.error1', { + postProcess: 'capitalizeFirstChar', + }) + ); setIsLoadingPublish(true); await qortalRequest({ action: 'PUBLISH_QDN_RESOURCE', @@ -555,14 +645,22 @@ const AvatarModal = ({ modalFunctionsAvatar }: AvatarModalProps) => { setHasAvatar(modalFunctionsAvatar?.data?.name, true); forceRefresh(); - showSuccess('Successfully published avatar'); + showSuccess( + t('core:avatar.responses.success', { + postProcess: 'capitalizeFirstChar', + }) + ); modalFunctionsAvatar.onOk(undefined); } catch (error) { if (error instanceof Error) { showError(error?.message); return; } - showError('Unable to publish avatar'); + showError( + t('core:avatar.responses.loading', { + postProcess: 'capitalizeFirstChar', + }) + ); } finally { dismissToast(loadId); setIsLoadingPublish(false); @@ -575,7 +673,11 @@ const AvatarModal = ({ modalFunctionsAvatar }: AvatarModalProps) => { aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" > - Publish Avatar + + {t('core:avatar.title', { + postProcess: 'capitalizeFirstChar', + })} + { (500 KB max. for GIFS){' '} setPickedAvatar(file)} mode="single"> - + @@ -643,10 +749,14 @@ const AvatarModal = ({ modalFunctionsAvatar }: AvatarModalProps) => { onClick={publishAvatar} autoFocus > - publish + {t('core:actions.publish', { + postProcess: 'capitalizeFirstChar', + })} @@ -665,6 +775,7 @@ const UpdateNameModal = ({ const [isNameAvailable, setIsNameAvailable] = useState( Availability.NULL ); + const { t } = useTranslation(); const [nameFee, setNameFee] = useState(null); const balance = useGlobal().auth.balance; @@ -723,16 +834,22 @@ const UpdateNameModal = ({ > {step === 1 && ( <> - Warning + + {t('core:warnings.warning', { + postProcess: 'capitalizeFirstChar', + })} + - Caution when updating your name + {t('core:update_name.title', { + postProcess: 'capitalizeFirstChar', + })} - If you update your Name, you will forfeit the resources associated - with the original Name. In other words, you will lose ownership of - the content under the original Name on QDN. Proceed with caution! + {t('core:warnings.update_name1', { + postProcess: 'capitalizeFirstChar', + })} @@ -742,23 +859,33 @@ const UpdateNameModal = ({ onClick={() => setStep(2)} autoFocus > - continue + {t('core:actions.continue', { + postProcess: 'capitalizeFirstChar', + })} )} {step === 2 && ( <> - Warning + + {t('core:warnings.warning', { + postProcess: 'capitalizeFirstChar', + })} + - Choose new name + {t('core:update_name.choose_name', { + postProcess: 'capitalizeFirstChar', + })} setNewName(e.target.value)} value={newName} - placeholder="Choose a name" + placeholder={t('core:new_name.choose_name', { + postProcess: 'capitalizeFirstChar', + })} /> {(!balance || (nameFee && balance && balance < nameFee)) && ( <> @@ -784,8 +913,11 @@ const UpdateNameModal = ({ }} /> - Your balance is {balance ?? 0} QORT. A name registration - requires a {nameFee} QORT fee + {t('core:update_name.balanceInfo', { + postProcess: 'capitalizeFirstChar', + nameFee: nameFee, + balance: balance ?? 0, + })} @@ -805,7 +937,12 @@ const UpdateNameModal = ({ color: theme.palette.text.primary, }} /> - {newName} is available + + {' '} + {t('core:update_name.name_available', { + name: newName, + })} + )} {isNameAvailable === Availability.NOT_AVAILABLE && ( @@ -821,7 +958,11 @@ const UpdateNameModal = ({ color: theme.palette.text.primary, }} /> - {newName} is unavailable + + {t('core:update_name.name_unavailable', { + name: newName, + })} + )} {isNameAvailable === Availability.LOADING && ( @@ -833,7 +974,11 @@ const UpdateNameModal = ({ }} > - Checking if name already existis + + {t('core:new_name.checking', { + postProcess: 'capitalizeFirstChar', + })} + )} @@ -850,14 +995,18 @@ const UpdateNameModal = ({ onClick={() => modalFunctionsUpdateName.onOk(newName.trim())} autoFocus > - continue + {t('core:actions.continue', { + postProcess: 'capitalizeFirstChar', + })} @@ -871,6 +1020,7 @@ interface SellNameModalProps { } const SellNameModal = ({ modalFunctionsSellName }: SellNameModalProps) => { + const { t } = useTranslation(); const [price, setPrice] = useState(0); return ( @@ -879,10 +1029,16 @@ const SellNameModal = ({ modalFunctionsSellName }: SellNameModalProps) => { aria-labelledby="alert-dialog-title" aria-describedby="alert-dialog-description" > - Selling name + + {t('core:sell_name.title', { + postProcess: 'capitalizeFirstChar', + })} + - Choose selling price + {t('core:sell_name.choose_price', { + postProcess: 'capitalizeFirstChar', + })} { onChange={(e) => setPrice(+e.target.value)} value={price} type="number" - placeholder="Choose a name" + placeholder={t('core:new_name.choose_price', { + postProcess: 'capitalizeFirstChar', + })} /> @@ -902,14 +1060,18 @@ const SellNameModal = ({ modalFunctionsSellName }: SellNameModalProps) => { onClick={() => modalFunctionsSellName.onOk(price)} autoFocus > - continue + {t('core:actions.continue', { + postProcess: 'capitalizeFirstChar', + })} diff --git a/src/i18n/locales/de/core.json b/src/i18n/locales/de/core.json new file mode 100644 index 0000000..18643be --- /dev/null +++ b/src/i18n/locales/de/core.json @@ -0,0 +1,96 @@ +{ + "header": { + "my_names": "meine Namen", + "market": "Namen zum Verkauf" + }, + "inputs": { + "filter_names": "Namen filtern" + }, + "actions": { + "new_name": "neuer Name", + "register_name": "Name registrieren", + "close": "schließen", + "update_avatar": "Avatar aktualisieren", + "set_avatar": "Avatar festlegen", + "update": "aktualisieren", + "sell": "verkaufen", + "cancel_sell": "Verkauf abbrechen", + "cancel": "abbrechen", + "continue": "fortfahren", + "publish": "veröffentlichen", + "buy": "kaufen", + "choose_image": "Bild auswählen" + }, + "new_name": { + "choose_name": "wähle einen Namen", + "balance_message": "Dein Guthaben beträgt {{balance}} QORT. Die Registrierung eines Namens kostet eine Gebühr von {{nameFee}} QORT.", + "name_available": "{{name}} ist verfügbar", + "name_unavailable": "{{name}} ist nicht verfügbar", + "checking_name": "überprüfe, ob der Name bereits existiert", + "responses": { + "success": "Name erfolgreich registriert", + "error": "Name konnte nicht registriert werden", + "loading": "Name wird registriert... bitte warten" + } + }, + "tables": { + "name": "Name", + "actions": "Aktionen" + }, + "update_name": { + "responses": { + "loading": "Name wird aktualisiert... bitte warten", + "success": "Name erfolgreich aktualisiert", + "error": "Name konnte nicht aktualisiert werden" + }, + "title": "Vorsicht beim Aktualisieren deines Namens", + "choose_name": "neuen Namen wählen", + "balance_info": "Dein Guthaben beträgt {{balance}} QORT. Die Registrierung eines Namens kostet eine Gebühr von {{nameFee}} QORT.", + "name_available": "{{name}} ist verfügbar", + "name_unavailable": "{{name}} ist nicht verfügbar" + }, + "sell_name": { + "responses": { + "loading": "Name wird zum Verkauf angeboten... bitte warten", + "success": "Name zum Verkauf angeboten", + "error1": "Primärname kann nicht verkauft werden, solange andere Namen vorhanden sind", + "error2": "Name konnte nicht zum Verkauf angeboten werden", + "error3": "ungültiger Preis" + }, + "title": "Name verkaufen", + "choose_price": "Verkaufspreis festlegen" + }, + "cancel_name": { + "responses": { + "loading": "Name wird vom Markt entfernt... bitte warten", + "success": "Name vom Markt entfernt", + "error": "Name konnte nicht vom Markt entfernt werden" + } + }, + "tooltips": { + "primary_name": "dies ist dein Primärname (Identität)" + }, + "warnings": { + "warning": "Warnung", + "primary_name_sell_caution": "Vorsicht beim Verkauf deines Primärnamens", + "primary_name_sell": "{{name}} ist dein Primärname. Wenn du Administrator einer privaten Gruppe bist, wird durch den Verkauf dieses Namens dein Gruppenschlüssel entfernt. Stelle sicher, dass ein anderer Administrator die neuesten Schlüssel neu verschlüsselt, bevor du verkaufst. Bitte mit Vorsicht fortfahren!", + "update_name1": "Wenn du deinen Namen aktualisierst, verlierst du die mit dem ursprünglichen Namen verbundenen Ressourcen. Anders gesagt: Du verlierst den Besitz der Inhalte unter dem ursprünglichen Namen im QDN. Bitte mit Vorsicht fortfahren!" + }, + "avatar": { + "responses": { + "loading": "Avatar wird veröffentlicht... bitte warten", + "success": "Avatar erfolgreich veröffentlicht", + "error1": "fehlende Daten", + "error2": "Avatar konnte nicht veröffentlicht werden" + }, + "title": "Avatar veröffentlichen" + }, + "market": { + "sale_price": "Verkaufspreis", + "responses": { + "loading": "versuche, Namen zu kaufen... bitte warten", + "success": "Name erfolgreich gekauft", + "error": "Name konnte nicht gekauft werden" + } + } +} diff --git a/src/i18n/locales/en/core.json b/src/i18n/locales/en/core.json index 712258b..f1e8f36 100644 --- a/src/i18n/locales/en/core.json +++ b/src/i18n/locales/en/core.json @@ -9,7 +9,17 @@ "actions": { "new_name": "new name", "register_name": "register name", - "close": "close" + "close": "close", + "update_avatar": "update avatar", + "set_avatar": "set avatar", + "update": "update", + "sell": "sell", + "cancel_sell": "cancel sell", + "cancel": "cancel", + "continue": "continue", + "publish": "publish", + "buy": "buy", + "choose_image": "choose Image" }, "new_name": { "choose_name": "choose a name", @@ -18,9 +28,69 @@ "name_unavailable": "{{name}} is unavailable", "checking_name": "checking if name already exists", "responses": { - "success": "successfully registered a name", + "success": "successfully registered the name", "error": "unable to register name", - "loading": "Registering name...please wait" + "loading": "registering name... please wait" + } + }, + "tables": { + "name": "name", + "actions": "actions" + }, + "update_name": { + "responses": { + "loading": "updating name... please wait", + "success": "successfully updated name", + "error": "unable to update name" + }, + "title": "caution when updating your name", + "choose_name": "choose new name", + "balance_info": "Your balance is {{balance}} QORT. A name registration requires a {{nameFee}} QORT fee.", + "name_available": "{{name}} is available", + "name_unavailable": "{{name}} is unavailable" + }, + "sell_name": { + "responses": { + "loading": "placing name for sale... please wait", + "success": "placed name for sale", + "error1": "cannot sell primary name while having other names", + "error2": "unable to place name for sale", + "error3": "invalid price" + }, + "title": "selling name", + "choose_price": "choose selling price" + }, + "cancel_name": { + "responses": { + "loading": "removing name from market... please wait", + "success": "removed name from market", + "error": "unable to remove name from market" + } + }, + "tooltips": { + "primary_name": "this is your primary name (identity)" + }, + "warnings": { + "warning": "warning", + "primary_name_sell_caution": "caution when selling your primary name", + "primary_name_sell": "{{name}} is your primary name. If you are an admin of a private group, selling this name will remove your group keys for the group. Make sure another admin re-encrypts the latest keys before selling. Proceed with caution!", + "update_name1": "if you update your Name, you will forfeit the resources associated with the original Name. In other words, you will lose ownership of the content under the original Name on QDN. Proceed with caution!" + }, + "avatar": { + "responses": { + "loading": "publishing avatar... please wait", + "success": "successfully published avatar", + "error1": "missing data", + "error2": "Unable to publish avatar" + }, + "title": "publish avatar" + }, + "market": { + "sale_price": "sale price", + "responses": { + "loading": "attempting to purchase name... please wait", + "success": "purchased name", + "error": "unable to purchase name" } } } diff --git a/src/i18n/locales/es/core.json b/src/i18n/locales/es/core.json index 2234ac5..0079ea9 100644 --- a/src/i18n/locales/es/core.json +++ b/src/i18n/locales/es/core.json @@ -1,6 +1,96 @@ { "header": { "my_names": "mis nombres", - "market": "" + "market": "nombres en venta" + }, + "inputs": { + "filter_names": "filtrar nombres" + }, + "actions": { + "new_name": "nuevo nombre", + "register_name": "registrar nombre", + "close": "cerrar", + "update_avatar": "actualizar avatar", + "set_avatar": "establecer avatar", + "update": "actualizar", + "sell": "vender", + "cancel_sell": "cancelar venta", + "cancel": "cancelar", + "continue": "continuar", + "publish": "publicar", + "buy": "comprar", + "choose_image": "elegir imagen" + }, + "new_name": { + "choose_name": "elige un nombre", + "balance_message": "Tu saldo es {{balance}} QORT. Registrar un nombre requiere una tarifa de {{nameFee}} QORT.", + "name_available": "{{name}} está disponible", + "name_unavailable": "{{name}} no está disponible", + "checking_name": "verificando si el nombre ya existe", + "responses": { + "success": "nombre registrado con éxito", + "error": "no se pudo registrar el nombre", + "loading": "registrando nombre... por favor espera" + } + }, + "tables": { + "name": "nombre", + "actions": "acciones" + }, + "update_name": { + "responses": { + "loading": "actualizando nombre... por favor espera", + "success": "nombre actualizado con éxito", + "error": "no se pudo actualizar el nombre" + }, + "title": "precaución al actualizar tu nombre", + "choose_name": "elige un nuevo nombre", + "balance_info": "Tu saldo es {{balance}} QORT. Registrar un nombre requiere una tarifa de {{nameFee}} QORT.", + "name_available": "{{name}} está disponible", + "name_unavailable": "{{name}} no está disponible" + }, + "sell_name": { + "responses": { + "loading": "poniendo el nombre a la venta... por favor espera", + "success": "nombre puesto a la venta", + "error1": "no puedes vender el nombre principal si tienes otros nombres", + "error2": "no se pudo poner el nombre a la venta", + "error3": "precio inválido" + }, + "title": "vender nombre", + "choose_price": "elige el precio de venta" + }, + "cancel_name": { + "responses": { + "loading": "eliminando nombre del mercado... por favor espera", + "success": "nombre eliminado del mercado", + "error": "no se pudo eliminar el nombre del mercado" + } + }, + "tooltips": { + "primary_name": "este es tu nombre principal (identidad)" + }, + "warnings": { + "warning": "advertencia", + "primary_name_sell_caution": "precaución al vender tu nombre principal", + "primary_name_sell": "{{name}} es tu nombre principal. Si eres administrador de un grupo privado, vender este nombre eliminará tus claves de grupo. Asegúrate de que otro administrador vuelva a cifrar las últimas claves antes de vender. ¡Procede con precaución!", + "update_name1": "si actualizas tu nombre, perderás los recursos asociados con el nombre original. En otras palabras, perderás la propiedad del contenido bajo el nombre original en QDN. ¡Procede con precaución!" + }, + "avatar": { + "responses": { + "loading": "publicando avatar... por favor espera", + "success": "avatar publicado con éxito", + "error1": "faltan datos", + "error2": "no se pudo publicar el avatar" + }, + "title": "publicar avatar" + }, + "market": { + "sale_price": "precio de venta", + "responses": { + "loading": "intentando comprar nombre... por favor espera", + "success": "nombre comprado", + "error": "no se pudo comprar el nombre" + } } } diff --git a/src/i18n/locales/fr/core.json b/src/i18n/locales/fr/core.json new file mode 100644 index 0000000..0366c23 --- /dev/null +++ b/src/i18n/locales/fr/core.json @@ -0,0 +1,96 @@ +{ + "header": { + "my_names": "mes noms", + "market": "noms en vente" + }, + "inputs": { + "filter_names": "filtrer les noms" + }, + "actions": { + "new_name": "nouveau nom", + "register_name": "enregistrer le nom", + "close": "fermer", + "update_avatar": "mettre à jour l'avatar", + "set_avatar": "définir l'avatar", + "update": "mettre à jour", + "sell": "vendre", + "cancel_sell": "annuler la vente", + "cancel": "annuler", + "continue": "continuer", + "publish": "publier", + "buy": "acheter", + "choose_image": "choisir une image" + }, + "new_name": { + "choose_name": "choisissez un nom", + "balance_message": "Votre solde est de {{balance}} QORT. L’enregistrement d’un nom nécessite des frais de {{nameFee}} QORT.", + "name_available": "{{name}} est disponible", + "name_unavailable": "{{name}} n’est pas disponible", + "checking_name": "vérification de l’existence du nom", + "responses": { + "success": "nom enregistré avec succès", + "error": "impossible d'enregistrer le nom", + "loading": "enregistrement du nom... veuillez patienter" + } + }, + "tables": { + "name": "nom", + "actions": "actions" + }, + "update_name": { + "responses": { + "loading": "mise à jour du nom... veuillez patienter", + "success": "nom mis à jour avec succès", + "error": "impossible de mettre à jour le nom" + }, + "title": "attention lors de la mise à jour de votre nom", + "choose_name": "choisir un nouveau nom", + "balance_info": "Votre solde est de {{balance}} QORT. L’enregistrement d’un nom nécessite des frais de {{nameFee}} QORT.", + "name_available": "{{name}} est disponible", + "name_unavailable": "{{name}} n’est pas disponible" + }, + "sell_name": { + "responses": { + "loading": "mise en vente du nom... veuillez patienter", + "success": "nom mis en vente", + "error1": "impossible de vendre le nom principal si d'autres noms existent", + "error2": "impossible de mettre le nom en vente", + "error3": "prix invalide" + }, + "title": "vendre un nom", + "choose_price": "choisissez un prix de vente" + }, + "cancel_name": { + "responses": { + "loading": "retrait du nom du marché... veuillez patienter", + "success": "nom retiré du marché", + "error": "impossible de retirer le nom du marché" + } + }, + "tooltips": { + "primary_name": "il s'agit de votre nom principal (identité)" + }, + "warnings": { + "warning": "avertissement", + "primary_name_sell_caution": "prudence lors de la vente de votre nom principal", + "primary_name_sell": "{{name}} est votre nom principal. Si vous êtes administrateur d’un groupe privé, la vente de ce nom supprimera vos clés de groupe. Assurez-vous qu’un autre administrateur chiffre à nouveau les dernières clés avant de vendre. Procédez avec prudence !", + "update_name1": "si vous mettez à jour votre nom, vous perdrez les ressources associées au nom d’origine. En d'autres termes, vous perdrez la propriété du contenu lié à l'ancien nom sur QDN. Procédez avec prudence !" + }, + "avatar": { + "responses": { + "loading": "publication de l'avatar... veuillez patienter", + "success": "avatar publié avec succès", + "error1": "données manquantes", + "error2": "impossible de publier l'avatar" + }, + "title": "publier l'avatar" + }, + "market": { + "sale_price": "prix de vente", + "responses": { + "loading": "tentative d'achat du nom... veuillez patienter", + "success": "nom acheté avec succès", + "error": "impossible d’acheter le nom" + } + } +} diff --git a/src/i18n/locales/it/core.json b/src/i18n/locales/it/core.json new file mode 100644 index 0000000..afcec4a --- /dev/null +++ b/src/i18n/locales/it/core.json @@ -0,0 +1,96 @@ +{ + "header": { + "my_names": "i miei nomi", + "market": "nomi in vendita" + }, + "inputs": { + "filter_names": "filtra nomi" + }, + "actions": { + "new_name": "nuovo nome", + "register_name": "registrare nome", + "close": "chiudi", + "update_avatar": "aggiorna avatar", + "set_avatar": "imposta avatar", + "update": "aggiorna", + "sell": "vendi", + "cancel_sell": "annulla vendita", + "cancel": "annulla", + "continue": "continua", + "publish": "pubblica", + "buy": "acquista", + "choose_image": "scegli immagine" + }, + "new_name": { + "choose_name": "scegli un nome", + "balance_message": "Il tuo saldo è {{balance}} QORT. La registrazione di un nome richiede una commissione di {{nameFee}} QORT.", + "name_available": "{{name}} è disponibile", + "name_unavailable": "{{name}} non è disponibile", + "checking_name": "verifica se il nome esiste già", + "responses": { + "success": "nome registrato con successo", + "error": "impossibile registrare il nome", + "loading": "registrazione del nome... attendere" + } + }, + "tables": { + "name": "nome", + "actions": "azioni" + }, + "update_name": { + "responses": { + "loading": "aggiornamento del nome... attendere", + "success": "nome aggiornato con successo", + "error": "impossibile aggiornare il nome" + }, + "title": "attenzione durante l'aggiornamento del nome", + "choose_name": "scegli un nuovo nome", + "balance_info": "Il tuo saldo è {{balance}} QORT. La registrazione di un nome richiede una commissione di {{nameFee}} QORT.", + "name_available": "{{name}} è disponibile", + "name_unavailable": "{{name}} non è disponibile" + }, + "sell_name": { + "responses": { + "loading": "messa in vendita del nome... attendere", + "success": "nome messo in vendita", + "error1": "non puoi vendere il nome principale se hai altri nomi", + "error2": "impossibile mettere il nome in vendita", + "error3": "prezzo non valido" + }, + "title": "vendere nome", + "choose_price": "scegli il prezzo di vendita" + }, + "cancel_name": { + "responses": { + "loading": "rimozione del nome dal mercato... attendere", + "success": "nome rimosso dal mercato", + "error": "impossibile rimuovere il nome dal mercato" + } + }, + "tooltips": { + "primary_name": "questo è il tuo nome principale (identità)" + }, + "warnings": { + "warning": "avviso", + "primary_name_sell_caution": "attenzione alla vendita del nome principale", + "primary_name_sell": "{{name}} è il tuo nome principale. Se sei amministratore di un gruppo privato, la vendita di questo nome rimuoverà le chiavi del gruppo. Assicurati che un altro amministratore re-critti le chiavi più recenti prima di vendere. Procedi con cautela!", + "update_name1": "se aggiorni il tuo nome, perderai le risorse associate al nome originale. In altre parole, perderai la proprietà dei contenuti collegati al nome originale su QDN. Procedi con cautela!" + }, + "avatar": { + "responses": { + "loading": "pubblicazione dell'avatar... attendere", + "success": "avatar pubblicato con successo", + "error1": "dati mancanti", + "error2": "impossibile pubblicare l'avatar" + }, + "title": "pubblica avatar" + }, + "market": { + "sale_price": "prezzo di vendita", + "responses": { + "loading": "tentativo di acquisto del nome... attendere", + "success": "nome acquistato con successo", + "error": "impossibile acquistare il nome" + } + } +} diff --git a/src/i18n/locales/ru/core.json b/src/i18n/locales/ru/core.json new file mode 100644 index 0000000..13d2faf --- /dev/null +++ b/src/i18n/locales/ru/core.json @@ -0,0 +1,96 @@ +{ + "header": { + "my_names": "мои имена", + "market": "имена на продажу" + }, + "inputs": { + "filter_names": "фильтровать имена" + }, + "actions": { + "new_name": "новое имя", + "register_name": "зарегистрировать имя", + "close": "закрыть", + "update_avatar": "обновить аватар", + "set_avatar": "установить аватар", + "update": "обновить", + "sell": "продать", + "cancel_sell": "отменить продажу", + "cancel": "отмена", + "continue": "продолжить", + "publish": "опубликовать", + "buy": "купить", + "choose_image": "выбрать изображение" + }, + "new_name": { + "choose_name": "выберите имя", + "balance_message": "Ваш баланс: {{balance}} QORT. Регистрация имени требует комиссии в размере {{nameFee}} QORT.", + "name_available": "{{name}} доступно", + "name_unavailable": "{{name}} недоступно", + "checking_name": "проверка существования имени", + "responses": { + "success": "имя успешно зарегистрировано", + "error": "не удалось зарегистрировать имя", + "loading": "регистрация имени... пожалуйста, подождите" + } + }, + "tables": { + "name": "имя", + "actions": "действия" + }, + "update_name": { + "responses": { + "loading": "обновление имени... пожалуйста, подождите", + "success": "имя успешно обновлено", + "error": "не удалось обновить имя" + }, + "title": "внимание при обновлении имени", + "choose_name": "выберите новое имя", + "balance_info": "Ваш баланс: {{balance}} QORT. Регистрация имени требует комиссии в размере {{nameFee}} QORT.", + "name_available": "{{name}} доступно", + "name_unavailable": "{{name}} недоступно" + }, + "sell_name": { + "responses": { + "loading": "выставление имени на продажу... пожалуйста, подождите", + "success": "имя выставлено на продажу", + "error1": "нельзя продавать основное имя при наличии других имён", + "error2": "не удалось выставить имя на продажу", + "error3": "некорректная цена" + }, + "title": "продажа имени", + "choose_price": "укажите цену продажи" + }, + "cancel_name": { + "responses": { + "loading": "удаление имени с рынка... пожалуйста, подождите", + "success": "имя удалено с рынка", + "error": "не удалось удалить имя с рынка" + } + }, + "tooltips": { + "primary_name": "это ваше основное имя (идентификатор)" + }, + "warnings": { + "warning": "предупреждение", + "primary_name_sell_caution": "осторожно при продаже основного имени", + "primary_name_sell": "{{name}} — это ваше основное имя. Если вы администратор частной группы, продажа этого имени приведет к удалению ваших ключей группы. Убедитесь, что другой администратор заново зашифрует последние ключи перед продажей. Действуйте с осторожностью!", + "update_name1": "если вы обновите имя, вы потеряете ресурсы, связанные с исходным именем. Иными словами, вы утратите право собственности на контент, размещённый под исходным именем в QDN. Действуйте с осторожностью!" + }, + "avatar": { + "responses": { + "loading": "публикация аватара... пожалуйста, подождите", + "success": "аватар успешно опубликован", + "error1": "отсутствуют данные", + "error2": "не удалось опубликовать аватар" + }, + "title": "опубликовать аватар" + }, + "market": { + "sale_price": "цена продажи", + "responses": { + "loading": "попытка покупки имени... пожалуйста, подождите", + "success": "имя успешно куплено", + "error": "не удалось купить имя" + } + } +} diff --git a/src/pages/Market.tsx b/src/pages/Market.tsx index 08c84cf..4b2db1c 100644 --- a/src/pages/Market.tsx +++ b/src/pages/Market.tsx @@ -110,7 +110,7 @@ export const Market = () => { > setValue(e.target.value)} diff --git a/src/pages/MyNames.tsx b/src/pages/MyNames.tsx index 3120593..5a89c73 100644 --- a/src/pages/MyNames.tsx +++ b/src/pages/MyNames.tsx @@ -54,7 +54,7 @@ export const MyNames = () => { {' '} setValue(e.target.value)} diff --git a/src/styles/Layout.tsx b/src/styles/Layout.tsx index 8b64540..e46b9a1 100644 --- a/src/styles/Layout.tsx +++ b/src/styles/Layout.tsx @@ -15,12 +15,12 @@ const Layout = () => { const navItems = [ { - label: t('core:header.my_names', { postProcess: 'capitalize' }), + label: t('core:header.my_names', { postProcess: 'capitalizeFirstChar' }), path: '/', Icon: FormatListBulletedIcon, }, { - label: t('core:header.market', { postProcess: 'capitalize' }), + label: t('core:header.market', { postProcess: 'capitalizeFirstChar' }), path: '/market', Icon: StorefrontIcon, },