diff --git a/libs/gi/localization/assets/locales/en/artifact.json b/libs/gi/localization/assets/locales/en/artifact.json
index df98210d51..299cfcd8ed 100644
--- a/libs/gi/localization/assets/locales/en/artifact.json
+++ b/libs/gi/localization/assets/locales/en/artifact.json
@@ -121,5 +121,11 @@
"rvSliderBtn": {
"maximum": "MRV",
"current": "RV"
+ },
+ "optExcludeModal": {
+ "excludeMsg": "Are you sure you want to exclude {{count}} artifacts from build optimization?",
+ "includeMsg": "Are you sure you want to include {{count}} artifacts to build optimization?",
+ "excludeBtn": "Exclude Artifacts",
+ "includeBtn": "Include Artifacts"
}
}
diff --git a/libs/gi/localization/assets/locales/en/build.json b/libs/gi/localization/assets/locales/en/build.json
new file mode 100644
index 0000000000..dd882dc9a2
--- /dev/null
+++ b/libs/gi/localization/assets/locales/en/build.json
@@ -0,0 +1,60 @@
+{
+ "buildDropdown": {
+ "tcBadge": "TC",
+ "equipped": "Equipped Build"
+ },
+ "buildCardTip": {
+ "edit": "Edit Build Settings",
+ "copyTc": "Copy to TC Builds",
+ "duplicate": "Duplicate Build",
+ "equip": "Equip Build",
+ "delete": "Delete Build"
+ },
+ "buildEqCard": {
+ "name": "Equipped Build",
+ "copy": {
+ "nameReal": "Duplicate of Equipped",
+ "nameTc": "Equipped Build - Copied",
+ "desc": "Copied from Equipped Build"
+ }
+ },
+ "buildRealCard": {
+ "copy": {
+ "nameReal": "Duplicate of {{name}}",
+ "nameTc": "{{name}} - Copied",
+ "equipped": "Equipped"
+ },
+ "edit": {
+ "title": "Build Settings",
+ "label": "Build Name",
+ "placeholder": "Build Name",
+ "desc": "Build Description"
+ }
+ },
+ "buildTcCard": {
+ "copy": {
+ "nameTc": "Duplicate of {{name}}"
+ },
+ "edit": {
+ "title": "Build Settings",
+ "label": "Build Name",
+ "placeholder": "Build Name",
+ "desc": "Build Description"
+ }
+ },
+ "equipBuildModal": {
+ "title": "Confirm Equipment Changes for <2>{{currentName}}2>",
+ "desc": "Do you want to make the changes shown below?",
+ "overwrite": "Copy the current equipment in <2>{{currentName}}2> to a new build. Otherwise, they will be overwritten.",
+ "label": "Build Name",
+ "newName": "Duplicate of {{currentName}}",
+ "cancel": "Cancel",
+ "equip": "Equip"
+ },
+ "compareBtn": {
+ "compare": "Compare",
+ "equipped": "Equipped ",
+ "crrBadge": "Current",
+ "tcBadge": "TC"
+ }
+}
diff --git a/libs/gi/localization/assets/locales/en/loadout.json b/libs/gi/localization/assets/locales/en/loadout.json
new file mode 100644
index 0000000000..9e7548e90e
--- /dev/null
+++ b/libs/gi/localization/assets/locales/en/loadout.json
@@ -0,0 +1,79 @@
+{
+ "loadoutSettings": {
+ "alert": "Loadouts provides character context data, including bonus stats, conditionals, multi-targets, optimization config, and stores builds. A single Loadout can be used for many teams.",
+ "title": "Build Management",
+ "builds": "Builds",
+ "newBuildBtn": "New Build",
+ "tcBuilds": "TC Builds",
+ "newTcBuildBtn": "New TC Build"
+ },
+ "mTargetEditor": {
+ "title": "Target Editor",
+ "rankMobile": "#",
+ "rank": "Rank #",
+ "desc": "Target Description",
+ "noReaction": "No Reactions"
+ },
+ "mTargetImport": {
+ "invalid": "Invalid Multi-Optimization Config",
+ "failed": "Data Import failed.",
+ "button": "Import Multi-Opt",
+ "title": "Import Multi-Opt",
+ "desc": "Import a Multi-opt in JSON form below.",
+ "label": "JSON Data",
+ "placeholder": "Paste your Team JSON here",
+ "import": "Import"
+ },
+ "showFormulas": {
+ "button": "Show Formulas & Calcs",
+ "title": "Formulas & Calculations"
+ },
+ "loDropdown": {
+ "createModal": {
+ "title": "Create a new Loadout For <2/>",
+ "label": "New Loadout Name",
+ "placeholder": "New Loadout Name",
+ "desc": "New Loadout Description",
+ "cancel": "Cancel",
+ "confirm": "Confirm"
+ },
+ "label": "Loadout: ",
+ "create": "Create a new Loadout",
+ "builds": "{{count}} Builds",
+ "tcs": "{{count}} TC Builds",
+ "multi": "{{count}} Multi-Opt"
+ },
+ "loadoutHeader": {
+ "builds": "Builds: ",
+ "tcBuilds": "TC Builds: ",
+ "mltTargets": "Custom multi-targets: ",
+ "optTarget": "Optimization Target:"
+ },
+ "loadoutEditor": {
+ "label": "Loadout Name",
+ "placeholder": "Loadout Name",
+ "desc": "Loadout Description",
+ "dupBtn": "Duplicate Loadout",
+ "delBtn": "Delete Loadout",
+ "optTarget": "Optimization Target",
+ "conditionals": "Conditionals: ",
+ "builds": "Builds",
+ "teams": "Teams",
+ "addNewTeam": "Add new Team",
+ "bonusStats": "Bonus Stats",
+ "mltTargets": "Custom multi-targets"
+ },
+ "loadoutDelModal": {
+ "title": "Delete Loadout: <1>{{name}}1>?",
+ "desc": "Deleting the Loadout will also delete the following data:",
+ "builds": "All saved builds: ",
+ "tcBuilds": "All saved TC builds: ",
+ "mTargets": "All Custom Multi-targets: ",
+ "bonus": "Bonus stats: ",
+ "condi": "Conditionals: ",
+ "optConfig": "Optimization Configuration",
+ "affected": "Any teams with this loadout will have this loadout removed from the team. Teams will not be deleted. Teams affected: ",
+ "cancel": "Cancel",
+ "delete": "Delete"
+ }
+}
diff --git a/libs/gi/localization/assets/locales/en/page_character.json b/libs/gi/localization/assets/locales/en/page_character.json
index d6092392d7..501b94e489 100644
--- a/libs/gi/localization/assets/locales/en/page_character.json
+++ b/libs/gi/localization/assets/locales/en/page_character.json
@@ -41,15 +41,25 @@
"duplicate": "Duplicate",
"target_one": "<0>{{count}}0> Target",
"target_other": "<0>{{count}}0> Targets",
- "jsonDescWarning": "It seems like you're trying to import a multi-opt config. This isn't the right place for that! Please go back one modal and press Import Multi-Opt."
+ "jsonDescWarning": "It seems like you're trying to import a multi-opt config. This isn't the right place for that! Please go back one modal and press Import Multi-Opt.",
+ "label": "Custom Multi-target Name",
+ "desc": "Custom Multi-target Description",
+ "export": "Export",
+ "confirm": "Are you sure you want to delete this target?",
+ "copyMsg": "Copied configuration to clipboard."
},
"addStats": {
"title": "Bonus Stats",
"info": "You can use these fields to add buffs/debuffs not directly supported in GO, such as food buffs, Abyss cards, or Superconduct. Please refer to the <1>Genshin Impact Wiki1> for specific values.",
- "label": "New Bonus Stat"
+ "label": "New Bonus Stat",
+ "main": "Main Stats",
+ "other": "Other Stats",
+ "misc": "Misc Stats",
+ "special": "<0>Special:0> "
},
"tabTheorycraft": {
"distribute": "Distribute",
+ "distInput": "Substats",
"compareToggle": {
"equipped": "Compare vs. equipped",
"tc": "Show TC stats"
@@ -107,5 +117,10 @@
"teammateUsing": {
"weapon": "Teammate <1>1> is using this weapon.",
"artifact": "Teammate <1>1> is using this <3>3>"
+ },
+ "charContentModal": {
+ "loadoutsWith": "Team Loadouts with <2/>",
+ "addLoAndTeam": "Add new Loadout+Team",
+ "addTeam": "Add new Team"
}
}
diff --git a/libs/gi/localization/assets/locales/en/page_character_optimize.json b/libs/gi/localization/assets/locales/en/page_character_optimize.json
index 84ee3df799..09d883bfdf 100644
--- a/libs/gi/localization/assets/locales/en/page_character_optimize.json
+++ b/libs/gi/localization/assets/locales/en/page_character_optimize.json
@@ -1,4 +1,5 @@
{
+ "specialized": "Specialized:",
"mainStat": {
"levelAssTooltip": {
"title": "Main Stat Level Assumption",
@@ -28,6 +29,22 @@
"upOptNoResults": "It looks like there aren't any artifacts available for upgrading that could enhance your setup. Your artifact filters might be too restrictive. Alternatively, try the main artifact optimizer to find a better build.",
"upOptInfo": "The Artifact Upgrader identifies artifacts with high potential to boost the Optimization Target's value, guiding you to artifacts worth leveling up.
As it only swaps one artifact at a time, for the best overall build across all artifacts, use the main artifact optimizer.",
"upOptEmptyBuild": "You're using a partially empty build. Since the Artifact Upgrader only swaps artifacts individually, completing a set is unlikely. It's recommended to begin with a base build, preferably generated from the main Optimizer.",
+ "upOptShowingNum": "Showing {{count}} out of {{value}} Artifacts",
+ "upOptChart": {
+ "est": " (est.)",
+ "prob": "Prob. upgrade{{est}}: ",
+ "average": "Average increase{{est}}: ",
+ "equipped": "Equipped",
+ "current": "Current on Build",
+ "incLabel": "Relative Increase to Target",
+ "probLabel": "Probability",
+ "const": " Constrained",
+ "exactDist": "Exact{{const}} Distribution",
+ "estimatedDist": "Estimated Distribution",
+ "currentTarget": "Current Target",
+ "currentLine": "Current Target Value",
+ "averageLine": "Average Increase"
+ },
"excludeArt": {
"title_exclude": "Excluded Artifacts",
"title_tooltip": "Add artifacts to this character's exclusion list. Artifacts in the exclusion list will not be considered for build generation.",
@@ -59,6 +76,8 @@
},
"usingState": "Using"
},
+ "useTeamArts": "Use artifacts in teammates' active builds",
+ "tcBadge": "TC build",
"allowPartial": "Allow Partial Builds (<5 artifacts)",
"constraintFilter": {
"title": "Minimum Build Constraints",
@@ -115,9 +134,39 @@
"cancel": "Cancel",
"generateBuilds": "Generate Builds"
},
+ "buildShowingNum": "Showing <2>{{count}}2> build generated for <6/>.",
+ "generatedOn": "Build generated on: ",
+ "selectChar": "Select a character to generate builds.",
+ "clearBuildsBtn": "Clear Builds",
+ "createBuildTc": {
+ "button": "New TC Build",
+ "title": "New Theorycraft Build",
+ "desc": "Copy over this build to a new TC Build",
+ "label": "TC Build Name",
+ "cancel": "Cancel",
+ "create": "Create"
+ },
+ "createBuildReal": {
+ "button": "New Build",
+ "title": "New Build",
+ "desc": "Copy over this build to a new build",
+ "label": "Build Name",
+ "cancel": "Cancel",
+ "create": "Create"
+ },
+ "buildDisplay": {
+ "equippedBadge": "(Equipped)",
+ "currentBadge": "(current build)",
+ "equipped": "Equipped",
+ "equipToCrr": "Equip to Current Build",
+ "oldWeapon": "Old Weapon",
+ "tcWeapon": "TC Weapon",
+ "newWeapon": "New Weapon"
+ },
"removeBuildButton": "Remove Build",
"theorycraftButton": "Theorycraft",
"currentlyEquippedBuild": "Currently Equipped",
+ "activeBuild": "Active Build",
"addBuildToList": "Add build to list",
"graphBuildLabel": "Graph #<1>{{count}}1>",
"buildCompleted": "Build Completed",
diff --git a/libs/gi/localization/assets/locales/en/page_team.json b/libs/gi/localization/assets/locales/en/page_team.json
index ffd44f99ad..0862bd5dc7 100644
--- a/libs/gi/localization/assets/locales/en/page_team.json
+++ b/libs/gi/localization/assets/locales/en/page_team.json
@@ -1,10 +1,79 @@
{
+ "searchLabel": {
+ "char": "Characters",
+ "team": "Team Name"
+ },
+ "addTeamBtn": "Add Team",
+ "importTeamBtn": "Import Team",
+ "importForm": {
+ "title": "Import Team",
+ "desc": "Import a team in JSON form below.",
+ "label": "JSON Data",
+ "placeholder": "Paste your Team JSON here",
+ "importBtn": "Import",
+ "error": {
+ "verifi": "Data verification failed.",
+ "import": "Data Import failed."
+ }
+ },
+ "teamDelModal": {
+ "teamName": "Delete Team:",
+ "alert": "Removing the team will remove: resonance buffs, and enemy configs stored in the team. Loadouts that are only in this team are also selected by default for deletion.",
+ "delBtn": "Delete",
+ "onlyCrrTeam": "Only in current team",
+ "usingMltTeams": "In {{count}} teams"
+ },
+ "teamSettings": {
+ "tab": {
+ "team": "Team Settings",
+ "char": "Character {{count}}"
+ },
+ "alert": {
+ "desc": "Teams are a container for 4 character loadouts. It provides a way for characters to apply team buffs, and configuration of enemy stats. Loadouts can be shared between teams.",
+ "first": "The first character in the team receives any \"active on-field character\" buffs, and cannot be empty."
+ },
+ "exportBtn": "Export Team",
+ "dupBtn": "Duplicate Team",
+ "deleteBtn": "Delete Team",
+ "addCharBtn": "Add Character",
+ "toFieldBtn": "To Field",
+ "onFieldBtn": "On-field Character"
+ },
+ "exportModal": {
+ "msg": "Copied team data to clipboard.",
+ "title": "Team Export",
+ "alert": "Export the team data to be imported by another user. All the team and loadout data (bonus stats, enemy config, optimize config) are exported. All exported non-TC builds are converted to TC builds.",
+ "selAll": "Select All",
+ "unselAll": "Unselect All",
+ "export": "Export",
+ "target": "Optimization Target:",
+ "mTargets": "Mtargets to Export",
+ "builds": "Builds to Export",
+ "equipped": "Equipped Build",
+ "tcBadge": "TC Build"
+ },
+ "enemyEditor": {
+ "enemyLevel": "Enemy ",
+ "defIgn": "DEF Ignore {{value}}%",
+ "defRed": "DEF Red. {{value}}%",
+ "announceBtn": "To get the specific resistance values of enemies, please visit the wiki.",
+ "note": "Note: Genshin Impact halves resistance shred values below 0%. For the sake of calculations enter the RAW value and GO will do the rest. (e.g. 10% - 20% = -10%)",
+ "immunity": "Immunity"
+ },
+ "teamComponents": {
+ "teamBuffs": "Received Team Buffs",
+ "tcBadge": "TC Build"
+ },
"buildInfo": {
"equipped": "This is the build currently equipped to your character, this represents in-game equipement and is persistent outside of the Loadout.",
"build": "A Build is comprised of a weapon and 5 artifacts.",
"tcbuild": "A Theorycraft Build allows defining a build by raw stats."
},
+ "charProfile": {
+ "button": "EDIT"
+ },
"buildTcCharOverride": {
+ "tip": "Set a specific level, constellation, ascension, or talent level for this TC build, that is different from the base character",
"btn": "Override Character Data for This TC build"
},
"team": {
diff --git a/libs/gi/localization/assets/locales/en/page_weapon.json b/libs/gi/localization/assets/locales/en/page_weapon.json
index ca6801b544..b89762830a 100644
--- a/libs/gi/localization/assets/locales/en/page_weapon.json
+++ b/libs/gi/localization/assets/locales/en/page_weapon.json
@@ -1,4 +1,5 @@
{
+ "weaponFilterTitle": "Weapon Filter",
"showingNum_one": "Showing <1>{{count}}1> out of {{value}} Weapon",
"showingNum_other": "Showing <1>{{count}}1> out of {{value}} Weapons",
"edit": "Edit Weapon",
@@ -18,5 +19,14 @@
"subheadings": {
"general": "General",
"inventory": "Inventory"
- }
+ },
+ "refinement": "Refinement <1>{{rank}}1>",
+ "weaponType": {
+ "sword": "Sword",
+ "claymore": "Claymore",
+ "polearm": "Polearm",
+ "bow": "Bow",
+ "catalyst": "Catalyst"
+ },
+ "tcBuild": "TC Build"
}
diff --git a/libs/gi/page-team/src/BuildDropdown.tsx b/libs/gi/page-team/src/BuildDropdown.tsx
index 5abe7b2046..de390f9d6f 100644
--- a/libs/gi/page-team/src/BuildDropdown.tsx
+++ b/libs/gi/page-team/src/BuildDropdown.tsx
@@ -4,7 +4,8 @@ import type { LoadoutDatum } from '@genshin-optimizer/gi/db'
import { useDatabase } from '@genshin-optimizer/gi/db-ui'
import CheckroomIcon from '@mui/icons-material/Checkroom'
import { Box, MenuItem } from '@mui/material'
-// TODO: Translation
+import { useTranslation } from 'react-i18next'
+
export default function BuildDropdown({
teamId,
loadoutDatum,
@@ -14,6 +15,7 @@ export default function BuildDropdown({
loadoutDatum: LoadoutDatum
dropdownBtnProps?: Omit
}) {
+ const { t } = useTranslation('build')
const database = useDatabase()
const { teamCharId, buildType, buildId, buildTcId } = loadoutDatum
const teamChar = database.teamChars.get(teamCharId)!
@@ -27,7 +29,9 @@ export default function BuildDropdown({
title={
{database.teams.getActiveBuildName(loadoutDatum)}
- {buildType === 'tc' && TC}
+ {buildType === 'tc' && (
+ {t`buildDropdown.tcBadge`}
+ )}
}
{...dropdownBtnProps}
@@ -37,7 +41,7 @@ export default function BuildDropdown({
onClick={() => onChangeLoadoutDatum({ buildType: 'equipped' })}
sx={{ display: 'flex', gap: 1 }}
>
- Equipped Build
+ {t`buildDropdown.equipped`}
{buildIds.map((bId) => {
const { name } = database.builds.get(bId)!
@@ -67,7 +71,7 @@ export default function BuildDropdown({
sx={{ display: 'flex', gap: 1 }}
>
{name}
- TC
+ {t`buildDropdown.tcBadge`}
)
})}
diff --git a/libs/gi/page-team/src/CharProfileCard.tsx b/libs/gi/page-team/src/CharProfileCard.tsx
index 3c3c953af6..3066ec56b1 100644
--- a/libs/gi/page-team/src/CharProfileCard.tsx
+++ b/libs/gi/page-team/src/CharProfileCard.tsx
@@ -14,10 +14,12 @@ import { input } from '@genshin-optimizer/gi/wr'
import DriveFileRenameOutlineIcon from '@mui/icons-material/DriveFileRenameOutline'
import { Box, Button, Grid, Typography } from '@mui/material'
import { useContext } from 'react'
+import { useTranslation } from 'react-i18next'
import { CharProfileCharEditor } from './CharProfileCharEditor'
/* Image card with star and name and level */
export default function CharacterProfileCard() {
+ const { t } = useTranslation('page_team')
const {
character: { key: characterKey },
} = useContext(CharacterContext)
@@ -36,8 +38,7 @@ export default function CharacterProfileCard() {
onClick={onShowEditor}
startIcon={}
>
- {/* TODO: translation */}
- EDIT
+ {t`charProfile.button`}
diff --git a/libs/gi/page-team/src/CharProfileCharEditor.tsx b/libs/gi/page-team/src/CharProfileCharEditor.tsx
index b2bca665bf..3cdacf2365 100644
--- a/libs/gi/page-team/src/CharProfileCharEditor.tsx
+++ b/libs/gi/page-team/src/CharProfileCharEditor.tsx
@@ -30,7 +30,7 @@ import {
Typography,
} from '@mui/material'
import { Suspense, useContext } from 'react'
-import { useTranslation } from 'react-i18next'
+import { Trans, useTranslation } from 'react-i18next'
import { BuildTcContext } from './BuildTcContext'
export function CharProfileCharEditor({
@@ -84,8 +84,11 @@ function Content({ onClose }: { onClose?: () => void }) {
- Set a specific level, constellation, ascension, or talent level
- for this TC build, that is different from the base character
+
+ Set a specific level, constellation, ascension, or talent
+ level for this TC build, that is different from the base
+ character
+
}
>
diff --git a/libs/gi/page-team/src/CharacterDisplay/Build/BuildEquipped.tsx b/libs/gi/page-team/src/CharacterDisplay/Build/BuildEquipped.tsx
index 40605a6cb4..f3a537eefd 100644
--- a/libs/gi/page-team/src/CharacterDisplay/Build/BuildEquipped.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/Build/BuildEquipped.tsx
@@ -13,7 +13,9 @@ import {
} from '@genshin-optimizer/gi/ui'
import { Grid } from '@mui/material'
import { useContext } from 'react'
+import { useTranslation } from 'react-i18next'
export function BuildEquipped({ active = false }: { active?: boolean }) {
+ const { t } = useTranslation('build')
const { teamId, teamCharId } = useContext(TeamCharacterContext)
const {
character: { key: characterKey, equippedArtifacts, equippedWeapon },
@@ -25,7 +27,7 @@ export function BuildEquipped({ active = false }: { active?: boolean }) {
})
const onDupe = () =>
database.teamChars.newBuild(teamCharId, {
- name: 'Duplicate of Equipped',
+ name: t`buildEqCard.copy.nameReal`,
artifactIds: equippedArtifacts,
weaponId: equippedWeapon,
})
@@ -40,14 +42,14 @@ export function BuildEquipped({ active = false }: { active?: boolean }) {
if (!newBuildTcId) return
// copy over name
database.buildTcs.set(newBuildTcId, {
- name: `Equipped Build - Copied`,
- description: 'Copied from Equipped Build',
+ name: t`buildEqCard.copy.nameTc`,
+ description: t`buildEqCard.copy.desc`,
})
}
return (
database.teamChars.newBuild(teamCharId, {
- name: `Duplicate of ${name}`,
+ name: t('buildRealCard.copy.nameReal', { name }),
artifactIds: artifactIds,
weaponId: weaponId,
})
@@ -112,7 +113,7 @@ export default function BuildReal({
void
}) {
+ const { t } = useTranslation('build')
const {
character: { key: characterKey },
} = useContext(CharacterContext)
@@ -233,7 +235,7 @@ function BuildEditor({
return (
@@ -244,14 +246,14 @@ function BuildEditor({
setName(e.target.value)}
/>
setDesc(e.target.value)}
multiline
diff --git a/libs/gi/page-team/src/CharacterDisplay/Build/BuildTc.tsx b/libs/gi/page-team/src/CharacterDisplay/Build/BuildTc.tsx
index d79d8603b3..f051c49da8 100644
--- a/libs/gi/page-team/src/CharacterDisplay/Build/BuildTc.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/Build/BuildTc.tsx
@@ -35,6 +35,7 @@ import {
Typography,
} from '@mui/material'
import { useContext, useDeferredValue, useEffect, useState } from 'react'
+import { useTranslation } from 'react-i18next'
export default function BuildTc({
buildTcId,
@@ -43,6 +44,7 @@ export default function BuildTc({
buildTcId: string
active?: boolean
}) {
+ const { t } = useTranslation('build')
const [open, onOpen, onClose] = useBoolState()
const { teamId, teamCharId } = useContext(TeamCharacterContext)
const database = useDatabase()
@@ -60,7 +62,7 @@ export default function BuildTc({
const onDupe = () =>
database.teamChars.newBuildTc(teamCharId, {
...structuredClone(buildTc),
- name: `Duplicate of ${name}`,
+ name: t('buildTcCard.copy.nameTc', { name }),
})
return (
<>
@@ -233,6 +235,7 @@ function BuildTcEditor({
buildTcId: string
onClose: () => void
}) {
+ const { t } = useTranslation('build')
const database = useDatabase()
const build = useBuildTc(buildTcId)!
@@ -268,7 +271,7 @@ function BuildTcEditor({
return (
@@ -279,14 +282,14 @@ function BuildTcEditor({
setName(e.target.value)}
/>
setDesc(e.target.value)}
multiline
diff --git a/libs/gi/page-team/src/CharacterDisplay/CompareBtn.tsx b/libs/gi/page-team/src/CharacterDisplay/CompareBtn.tsx
index 99debffc31..340d019d90 100644
--- a/libs/gi/page-team/src/CharacterDisplay/CompareBtn.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/CompareBtn.tsx
@@ -5,18 +5,19 @@ import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'
import type { ButtonGroupProps } from '@mui/material'
import { Button, ButtonGroup, MenuItem } from '@mui/material'
import { useContext } from 'react'
+import { useTranslation } from 'react-i18next'
/**
* The UI component that modifies the compare data in a TeamChar.
* This is used in conjuction with useCompareData hook to supply a compareData to the compare UI.
*/
-// TODO: Translation
export default function CompareBtn({
buttonGroupProps = {},
}: {
buttonGroupProps?: ButtonGroupProps
}) {
+ const { t } = useTranslation('build')
const database = useDatabase()
const {
teamId,
@@ -40,11 +41,11 @@ export default function CompareBtn({
{database.buildTcs.get(compareBuildTcId)?.name ?? ''}{' '}
- TC
+ {t`compareBtn.tcBadge`}
) : (
- 'Equipped'
+ t`compareBtn.equipped`
)
const current =
(compareType === 'equipped' && buildType === 'equipped') ||
@@ -65,7 +66,7 @@ export default function CompareBtn({
})
}
>
- Compare
+ {t`compareBtn.compare`}
- Current
+ {t`compareBtn.crrBadge`}
)}
>
@@ -87,10 +88,10 @@ export default function CompareBtn({
})
}
>
- Equipped{' '}
+ {t`compareBtn.equipped`}
{buildType === 'equipped' && (
- Current
+ {t`compareBtn.crrBadge`}
)}
@@ -108,7 +109,7 @@ export default function CompareBtn({
{database.builds.get(bId)!.name}{' '}
{buildType === 'real' && bId === buildId && (
- Current
+ {t`compareBtn.crrBadge`}
)}
@@ -125,11 +126,11 @@ export default function CompareBtn({
>
{database.buildTcs.get(bTcId)?.name ?? ''}{' '}
- TC
+ {t`compareBtn.tcBadge`}
{buildType === 'tc' && bTcId === buildTcId && (
- Current
+ {t`compareBtn.crrBadge`}
)}
diff --git a/libs/gi/page-team/src/CharacterDisplay/CustomMultiTarget/CustomMultiTargetCard.tsx b/libs/gi/page-team/src/CharacterDisplay/CustomMultiTarget/CustomMultiTargetCard.tsx
index 1e3dfcb106..9b8116ab6d 100644
--- a/libs/gi/page-team/src/CharacterDisplay/CustomMultiTarget/CustomMultiTargetCard.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/CustomMultiTarget/CustomMultiTargetCard.tsx
@@ -88,14 +88,14 @@ export default function CustomMultiTargetCard({
(index: number) => () => {
if (
Object.values(target.targets[index].bonusStats).length &&
- !window.confirm(`Are you sure you want to delete this target?`)
+ !window.confirm(t`multiTarget.confirm`)
)
return
const targets = [...target.targets]
targets.splice(index, 1)
setTarget({ ...target, targets })
},
- [target, setTarget]
+ [target, setTarget, t]
)
const [selectedTarget, setSelectedTarget] = useState(-1)
@@ -124,7 +124,7 @@ export default function CustomMultiTargetCard({
const copyToClipboard = () =>
navigator.clipboard
.writeText(JSON.stringify(target))
- .then(() => alert('Copied configuration to clipboard.'))
+ .then(() => alert(t`multiTarget.copyMsg`))
.catch(console.error)
const customTargetDisplays = useMemo(
@@ -192,7 +192,7 @@ export default function CustomMultiTargetCard({
>
setTarget((target) => ({
@@ -204,7 +204,7 @@ export default function CustomMultiTargetCard({
{description && descIsJson && }
{
setDescIsJson(
@@ -243,7 +243,7 @@ export default function CustomMultiTargetCard({
startIcon={}
sx={{ flexGrow: 1 }}
>
- Export
+ {t`multiTarget.export`}
diff --git a/libs/gi/page-team/src/CharacterDisplay/CustomMultiTarget/MTargetEditor.tsx b/libs/gi/page-team/src/CharacterDisplay/CustomMultiTarget/MTargetEditor.tsx
index e941395b2b..ed626cf15c 100644
--- a/libs/gi/page-team/src/CharacterDisplay/CustomMultiTarget/MTargetEditor.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/CustomMultiTarget/MTargetEditor.tsx
@@ -72,7 +72,7 @@ export default function MTargetEditor({
setTargetIndex: (ind?: number) => void
onDup: () => void
}) {
- const { t } = useTranslation('page_character')
+ const { t } = useTranslation(['page_character', 'loadout'])
const {
character: { key: characterKey },
} = useContext(CharacterContext)
@@ -146,14 +146,16 @@ export default function MTargetEditor({
}}
onClick={() => setcollapse((c) => !c)}
>
- Target Editor
+ {t`loadout:mTargetEditor.title`}
{collapse ? : }
- {isMobile ? '#' : 'Rank #'}
+ {isMobile
+ ? t`loadout:mTargetEditor.rankMobile`
+ : t`loadout:mTargetEditor.rank`}
),
}}
@@ -286,7 +288,7 @@ export default function MTargetEditor({
setCustomTarget({ ...customTarget, description })
@@ -315,7 +317,7 @@ function ReactionDropdown({
infusionAura?: InfusionAuraElementKey
}) {
const ele = node.info.variant ?? 'physical'
- const { t } = useTranslation('page_character')
+ const { t } = useTranslation(['page_character', 'loadout'])
if (
!['pyro', 'hydro', 'cryo', 'electro', 'dendro'].some(
@@ -343,7 +345,7 @@ function ReactionDropdown({
return (
{reactions.map((rm) => (
- Builds
+ {t`loadoutSettings.builds`}
}
color="info"
size="small"
onClick={() => database.teamChars.newBuild(teamCharId)}
>
- New Build
+ {t`loadoutSettings.newBuildBtn`}
@@ -156,7 +156,7 @@ function BuildManagementContent() {
- TC Builds
+ {t`loadoutSettings.tcBuilds`}
}
color="info"
@@ -165,7 +165,7 @@ function BuildManagementContent() {
database.teamChars.newBuildTcFromBuild(teamCharId, weaponTypeKey)
}
>
- New TC Build
+ {t`loadoutSettings.newTcBuildBtn`}
@@ -215,6 +215,7 @@ function DetailStatButton({ buttonProps = {} }: { buttonProps?: ButtonProps }) {
)
}
function FormulasButton({ buttonProps = {} }: { buttonProps?: ButtonProps }) {
+ const { t } = useTranslation('loadout')
const { onModalOpen } = useContext(FormulaDataContext)
return (
- Show Formulas {'&'} Calcs
+ {t`showFormulas.button`}
)
}
diff --git a/libs/gi/page-team/src/CharacterDisplay/StatModal.tsx b/libs/gi/page-team/src/CharacterDisplay/StatModal.tsx
index adeada1c3a..0daf6e41b6 100644
--- a/libs/gi/page-team/src/CharacterDisplay/StatModal.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/StatModal.tsx
@@ -176,6 +176,7 @@ function StatDisplayContent({
}
function MainStatsCards() {
+ const { t } = useTranslation('page_character')
const {
character: { key: characterKey },
} = useContext(CharacterContext)
@@ -208,7 +209,7 @@ function MainStatsCards() {
-
+
- Special:{' '}
+
+ Special:{' '}
+
-
+
{!!miscStatReadNodes.length && (
-
+
diff --git a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/ChartCard/CustomTooltip.tsx b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/ChartCard/CustomTooltip.tsx
index 477e6c5dbd..9cd4440ff7 100644
--- a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/ChartCard/CustomTooltip.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/ChartCard/CustomTooltip.tsx
@@ -133,8 +133,7 @@ export default function CustomTooltip({
)}
{activeBuild && (
- {/* TODO: Translation */}
- Active Build
+ {t`activeBuild`}
)}
{generLabel && {generLabel}}
diff --git a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/ExcludeArt.tsx b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/ExcludeArt.tsx
index ad61073e97..80d578dd7b 100644
--- a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/ExcludeArt.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/ExcludeArt.tsx
@@ -226,7 +226,7 @@ function ExcludeArtRedButtons({
onExclude: (ids: string[]) => void
onInclude: (ids: string[]) => void
}) {
- const { t } = useTranslation(['artifact', 'ui'])
+ const { t } = useTranslation('artifact')
const { numExclude, numInclude } = useMemo(() => {
const excludedFiltered = artExclusion.filter((i) => artifactIds.includes(i))
@@ -237,13 +237,11 @@ function ExcludeArtRedButtons({
}, [artifactIds, artExclusion])
const excludeArtifacts = () =>
- window.confirm(
- `Are you sure you want to exclude ${numExclude} artifacts from build optimization?`
- ) && onExclude(artifactIds)
+ window.confirm(t('optExcludeModal.excludeMsg', { count: numExclude })) &&
+ onExclude(artifactIds)
const includeArtifacts = () =>
- window.confirm(
- `Are you sure you want to include ${numInclude} artifacts to build optimization?`
- ) && onInclude(artifactIds)
+ window.confirm(t('optExcludeModal.includeMsg', { count: numInclude })) &&
+ onInclude(artifactIds)
return (
@@ -255,9 +253,7 @@ function ExcludeArtRedButtons({
onClick={excludeArtifacts}
startIcon={}
>
-
- Exclude Artifacts
-
+ {t`optExcludeModal.excludeBtn`}
{numExclude}
@@ -271,9 +267,7 @@ function ExcludeArtRedButtons({
onClick={includeArtifacts}
startIcon={}
>
-
- Include Artifacts
-
+ {t`optExcludeModal.includeBtn`}
{numInclude}
diff --git a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/UseTeammateArt.tsx b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/UseTeammateArt.tsx
index 3112b73658..588429003b 100644
--- a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/UseTeammateArt.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/Components/UseTeammateArt.tsx
@@ -16,6 +16,7 @@ import {
} from '@mui/material'
import type { ReactNode } from 'react'
import { Suspense, memo, useContext } from 'react'
+import { useTranslation } from 'react-i18next'
export const UseTeammateArt = memo(function UseTeammateArt({
totalTally,
useTeammateBuild,
@@ -25,6 +26,7 @@ export const UseTeammateArt = memo(function UseTeammateArt({
useTeammateBuild: boolean
disabled?: boolean
}) {
+ const { t } = useTranslation('page_character_optimize')
const database = useDatabase()
const {
teamCharId,
@@ -92,7 +94,7 @@ export const UseTeammateArt = memo(function UseTeammateArt({
) : (
- TC build
+ {t`tcBadge`}
)}
@@ -120,8 +122,7 @@ export const UseTeammateArt = memo(function UseTeammateArt({
disabled={disabled}
>
- {/* TODO: Translation */}
- Use artifacts in teammates' active builds
+ {t`useTeamArts`}
diff --git a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/index.tsx b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/index.tsx
index 97cccbdd57..82f30ee8e8 100644
--- a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/index.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabOptimize/index.tsx
@@ -547,6 +547,9 @@ export default function TabBuild() {
)
const getNormBuildLabel = useCallback((index: number) => `#${index + 1}`, [])
+ const buildShowingCount =
+ builds.length + (graphBuilds ? graphBuilds.length : 0)
+
return (
{noArtifact && }
@@ -787,20 +790,29 @@ export default function TabBuild() {
{builds ? (
- Showing{' '}
-
- {builds.length + (graphBuilds ? graphBuilds.length : 0)}
- {' '}
- build generated for {characterName}.{' '}
+
+ Showing{' '}
+ {{ count: buildShowingCount } as any}{' '}
+ build generated for{' '}
+
+ .
+ {' '}
{!!buildDate && (
- Build generated on:{' '}
+ {t`generatedOn`}
{new Date(buildDate).toLocaleString()}
)}
) : (
- Select a character to generate builds.
+ {t`selectChar`}
)}
- Clear Builds
+ {t`clearBuildsBtn`}
@@ -998,6 +1010,7 @@ const BuildItemWrapper = memo(function BuildItemWrapper({
)
})
function CopyTcButton({ build }: { build: GeneratedBuild }) {
+ const { t } = useTranslation('page_character_optimize')
const [name, setName] = useState('')
const [showTcPrompt, onShowTcPrompt, OnHideTcPrompt] = useBoolState()
@@ -1033,14 +1046,13 @@ function CopyTcButton({ build }: { build: GeneratedBuild }) {
startIcon={}
onClick={onShowTcPrompt}
>
- New TC Build
+ {t`createBuildTc.button`}
{/* TODO: Dialog Wanted to use a Dialog here, but was having some weird issues with closing out of it */}
- {/* TODO: Translation */}
@@ -1051,19 +1063,21 @@ function CopyTcButton({ build }: { build: GeneratedBuild }) {
- Copy over this build to a new TC Build
+ {t`createBuildTc.desc`}
setName(e.target.value)}
autoFocus
margin="dense"
- label="TC Build Name"
+ label={t`createBuildTc.label`}
fullWidth
/>
- Cancel
+ {t`createBuildTc.cancel`}
- Create
+ {t`createBuildTc.create`}
@@ -1077,6 +1091,7 @@ function CopyBuildButton({
}: {
build: GeneratedBuild
}) {
+ const { t } = useTranslation('page_character_optimize')
const [name, setName] = useState('')
const [showPrompt, onShowPrompt, OnHidePrompt] = useBoolState()
@@ -1102,10 +1117,9 @@ function CopyBuildButton({
startIcon={}
onClick={onShowPrompt}
>
- New Build
+ {t`createBuildReal.button`}
{/* TODO: Dialog Wanted to use a Dialog here, but was having some weird issues with closing out of it */}
- {/* TODO: Translation */}
@@ -1124,20 +1138,22 @@ function CopyBuildButton({
- Copy over this build to a new build
+ {t`createBuildReal.desc`}
diff --git a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabTheorycraft/index.tsx b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabTheorycraft/index.tsx
index 529ce567a7..38f1ed0df8 100644
--- a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabTheorycraft/index.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabTheorycraft/index.tsx
@@ -336,7 +336,7 @@ export default function TabTheorycraft() {
value={distributedSubstats}
disabled={!optimizationTarget || solving}
onChange={(v) => v !== undefined && setDistributedSubstats(v)}
- endAdornment={'Substats'}
+ endAdornment={t`tabTheorycraft.distInput`}
sx={{
borderRadius: 1,
px: 1,
@@ -390,19 +390,19 @@ export default function TabTheorycraft() {
The selected Optimization target and constraints scales with:{' '}
- {[...scalesWith]
- .map((k) => (
-
-
-
-
- ))
- .flatMap((value, index, array) => {
- if (index === array.length - 2)
- return [value, , and ]
- if (index === array.length - 1) return value
- return [value, , ]
- })}
+ {new Intl.ListFormat()
+ .format(Array(scalesWith.size).fill('\u200B'))
+ .split(/([^\u200B]+)/)
+ .map((str, i) =>
+ str === '\u200B'
+ ? ((k) => (
+
+
+
+
+ ))([...scalesWith][i / 2])
+ : str
+ )}
. The solver will only distribute stats to these substats.
{' '}
diff --git a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabUpgradeOpt/LevelFilter.tsx b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabUpgradeOpt/LevelFilter.tsx
index 817c79acc4..e09fae832c 100644
--- a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabUpgradeOpt/LevelFilter.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabUpgradeOpt/LevelFilter.tsx
@@ -6,7 +6,6 @@ import { CardContent, Divider, Tooltip, Typography } from '@mui/material'
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
-// TODO: Translation
export const LevelFilter = memo(function LevelFilter({
levelTotal,
upOptLevelLow,
diff --git a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabUpgradeOpt/UpgradeOptChartCard.tsx b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabUpgradeOpt/UpgradeOptChartCard.tsx
index 16ad56ae51..f1087a0252 100644
--- a/libs/gi/page-team/src/CharacterDisplay/Tabs/TabUpgradeOpt/UpgradeOptChartCard.tsx
+++ b/libs/gi/page-team/src/CharacterDisplay/Tabs/TabUpgradeOpt/UpgradeOptChartCard.tsx
@@ -19,6 +19,7 @@ import { uiInput as input } from '@genshin-optimizer/gi/wr'
import CheckroomIcon from '@mui/icons-material/Checkroom'
import { Box, Button, Divider, Grid, Tooltip, Typography } from '@mui/material'
import { useCallback, useContext, useEffect, useMemo } from 'react'
+import { useTranslation } from 'react-i18next'
import {
Area,
ComposedChart,
@@ -146,6 +147,7 @@ function UpgradeOptChartCardGraph({
upOptCalc,
ix,
}: Props) {
+ const { t } = useTranslation('page_character_optimize')
const upArt = upOptCalc.artifacts[ix]
const database = useDatabase()
const [, forceUpdate] = useForceUpdate()
@@ -224,13 +226,13 @@ function UpgradeOptChartCardGraph({
const probUpgradeText = (
- Prob. upgrade{isExact ? '' : ' (est.)'}:{' '}
+ {t('upOptChart.prob', { est: isExact ? '' : t`upOptChart.est` })}
{(100 * reportP).toFixed(1)}%
)
const avgIncText = (
- Average increase{isExact ? '' : ' (est.)'}:{' '}
+ {t('upOptChart.average', { est: isExact ? '' : t`upOptChart.est` })}
{reportD <= 0 ? '' : '+'}
{((100 * reportD) / thr0).toFixed(1)}%
@@ -262,9 +264,9 @@ function UpgradeOptChartCardGraph({
>
{isCurrentlyEquipped ? (
- Equipped
+ {t`upOptChart.equipped`}
) : (
- {'Current on Build'}
+ {t`upOptChart.current`}
)}
@@ -291,7 +293,7 @@ function UpgradeOptChartCardGraph({
tickFormatter={(v) => `${v <= 0 ? '' : '+'}${v}%`}
>
@@ -112,7 +113,8 @@ export function LoadoutDropdown({
>
{label ? (
- Loadout: {name}
+ {t`loDropdown.label`}
+ {name}
) : (
{name}
@@ -121,7 +123,7 @@ export function LoadoutDropdown({
}
{...dropdownBtnProps}
>
-
+
{teamCharIds.map((tcId) => {
const { name, buildIds, buildTcIds, customMultiTargets } =
database.teamChars.get(tcId)!
@@ -137,15 +139,15 @@ export function LoadoutDropdown({
color={buildIds.length ? 'primary' : 'secondary'}
sx={{ marginLeft: 'auto' }}
>
- {buildIds.length} Builds
+ {t(`loDropdown.builds`, { count: buildIds.length })}
- {buildTcIds.length} TC Builds
+ {t(`loDropdown.tcs`, { count: buildTcIds.length })}
- {customMultiTargets.length} Multi-Opt
+ {t(`loDropdown.multi`, { count: customMultiTargets.length })}
)
diff --git a/libs/gi/page-team/src/TeamCharacterSelector.tsx b/libs/gi/page-team/src/TeamCharacterSelector.tsx
index 9f476985eb..77dc3e52da 100644
--- a/libs/gi/page-team/src/TeamCharacterSelector.tsx
+++ b/libs/gi/page-team/src/TeamCharacterSelector.tsx
@@ -203,7 +203,7 @@ export default function TeamCharacterSelector({
icon={}
iconPosition="start"
value={'team'}
- label={'Team Settings'}
+ label={t`teamSettings.tab.team`}
onClick={() => navigate(`/teams/${teamId}/`)}
/>
{loadoutData.map((loadoutDatum, ind) => {
@@ -227,7 +227,7 @@ export default function TeamCharacterSelector({
teamCharKey ? (
) : (
- `Character ${ind + 1}` // TODO: Translation
+ t('teamSettings.tab.char', { count: ind + 1 })
)
}
onClick={() =>
diff --git a/libs/gi/page-team/src/TeamSetting/TeamComponents.tsx b/libs/gi/page-team/src/TeamSetting/TeamComponents.tsx
index affefead4e..5027d92d38 100644
--- a/libs/gi/page-team/src/TeamSetting/TeamComponents.tsx
+++ b/libs/gi/page-team/src/TeamSetting/TeamComponents.tsx
@@ -41,9 +41,11 @@ import {
Typography,
} from '@mui/material'
import { Suspense, useContext, useMemo } from 'react'
+import { useTranslation } from 'react-i18next'
import { Link } from 'react-router-dom'
export function TeamBuffDisplay() {
+ const { t } = useTranslation('page_team')
const { data } = useContext(DataContext)
const nodes = useMemo(() => {
const teamBuffs = data.getTeamBuff()
@@ -70,7 +72,7 @@ export function TeamBuffDisplay() {
>
}>
- Received Team Buffs
+ {t`teamComponents.teamBuffs`}
{nodes.length}
@@ -192,6 +194,7 @@ function TcEquipmentRow({
}: {
loadoutDatum: LoadoutDatum
}) {
+ const { t } = useTranslation('page_team')
const {
artifact: { sets },
} = useBuildTc(buildTcId)!
@@ -205,8 +208,7 @@ function TcEquipmentRow({
gap: 1,
}}
>
- {/* TODO: Translation */}
- TC Build
+ {t`teamComponents.tcBadge`}
{Object.entries(sets).map(([setKey, number]) => (
void
teamId: string
}) {
+ const { t } = useTranslation('page_team')
const database = useDatabase()
const team = useTeam(teamId)!
const { loadoutData } = team
@@ -93,7 +94,7 @@ export default function TeamExportModal({
const dataStr = JSON.stringify(data)
navigator.clipboard
.writeText(dataStr)
- .then(() => alert('Copied team data to clipboard.'))
+ .then(() => alert(t`exportModal.msg`))
.catch(console.error)
}
const [selAll, setSelAll] = useState(true)
@@ -134,7 +135,7 @@ export default function TeamExportModal({
@@ -151,12 +152,19 @@ export default function TeamExportModal({
}}
>
- Export the team data to be imported by another user. All the team
- and loadout data (bonus stats, enemy config, optimize config) are
- exported. All exported non-TC builds are converted to TC builds.
+
+ Export the team data to be imported by another user. All the
+ team and loadout data (bonus stats, enemy config, optimize
+ config) are exported. All exported non-TC builds are converted
+ to TC builds.
+
-
- {selAll ? 'Select All' : 'Unselect All'}
+
+ {selAll ? t`exportModal.selAll` : t`exportModal.unselAll`}
@@ -189,7 +197,7 @@ export default function TeamExportModal({
sx={{ display: 'flex', gap: 2, justifyContent: 'flex-end' }}
>
- Export
+ {t`exportModal.export`}
@@ -205,6 +213,7 @@ function LoadoutSetting({
setting: LoadoutExportSetting
setSetting: (loadoutExportSetting: Partial) => void
}) {
+ const { t } = useTranslation('page_team')
const database = useDatabase()
const teamChar = useTeamChar(loadout.teamCharId)!
const {
@@ -258,7 +267,7 @@ function LoadoutSetting({
sx={{ display: 'flex', gap: 1, alignItems: 'center' }}
>
- Optimization Target:
+ {t`exportModal.target`}
- Mtargets to Export
+ {t`exportModal.mTargets`}
@@ -326,7 +335,7 @@ function LoadoutSetting({
- Builds to Export
+ {t`exportModal.builds`}
@@ -342,7 +351,7 @@ function LoadoutSetting({
tabIndex={-1}
disableRipple
/>
-
+
{buildIds.map((buildId) => {
@@ -395,7 +404,7 @@ function LoadoutSetting({
- {buildTc.name} TC Build
+ {buildTc.name} {t`exportModal.tcBadge`}
}
/>
diff --git a/libs/gi/page-team/src/TeamSetting/index.tsx b/libs/gi/page-team/src/TeamSetting/index.tsx
index 4e5db5ec75..cbefefe96e 100644
--- a/libs/gi/page-team/src/TeamSetting/index.tsx
+++ b/libs/gi/page-team/src/TeamSetting/index.tsx
@@ -20,6 +20,7 @@ import DeleteForeverIcon from '@mui/icons-material/DeleteForever'
import type { ButtonProps } from '@mui/material'
import { Alert, Box, Button, CardContent, Grid } from '@mui/material'
import { Suspense, useMemo, useState } from 'react'
+import { Trans, useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import BuildDropdown from '../BuildDropdown'
import { LoadoutDropdown } from '../LoadoutDropdown'
@@ -27,7 +28,6 @@ import { ResonanceDisplay } from './ResonanceDisplay'
import { TeammateDisplay } from './TeamComponents'
import TeamExportModal from './TeamExportModal'
-// TODO: Translation
export default function TeamSetting({
teamId,
teamData,
@@ -36,6 +36,7 @@ export default function TeamSetting({
teamData?: TeamData
buttonProps?: ButtonProps
}) {
+ const { t } = useTranslation('page_team')
const navigate = useNavigate()
const database = useDatabase()
const [show, onShow, onHide] = useBoolState()
@@ -64,7 +65,7 @@ export default function TeamSetting({
disabled={noChars}
onClick={onShow}
>
- Export Team
+ {t`teamSettings.exportBtn`}
}
>
- Duplicate Team
+ {t`teamSettings.dupBtn`}
}
>
- Delete Team
+ {t`teamSettings.deleteBtn`}
@@ -102,6 +103,7 @@ function TeamEditor({
teamId: string
teamData?: TeamData
}) {
+ const { t } = useTranslation('page_team')
const database = useDatabase()
const team = database.teams.get(teamId)!
const { loadoutData } = team
@@ -184,8 +186,10 @@ function TeamEditor({
- The first character in the team receives any "active on-field character"
- buffs, and cannot be empty.
+
+ The first character in the team receives any "active on-field
+ character" buffs, and cannot be empty.
+
{loadoutData.map((loadoutDatum, ind) => (
@@ -207,7 +211,7 @@ function TeamEditor({
disabled={!!ind && !loadoutData.some((id) => id)}
startIcon={}
>
- Add Character
+ {t`teamSettings.addCharBtn`}
)}
@@ -229,6 +233,7 @@ function CharSelButton({
teamData?: TeamData
onClickChar: () => void
}) {
+ const { t } = useTranslation('page_team')
const database = useDatabase()
const { teamCharId } = loadoutDatum
const { key: characterKey } = database.teamChars.get(teamCharId)!
@@ -291,11 +296,11 @@ function CharSelButton({
/>
{index ? (
- To Field
+ {t`teamSettings.toFieldBtn`}
) : (
- On-field Character
+ {t`teamSettings.onFieldBtn`}
)}
{dataContextValue && (
diff --git a/libs/gi/page-team/src/index.tsx b/libs/gi/page-team/src/index.tsx
index e488e7c11f..d50c5f6ae3 100644
--- a/libs/gi/page-team/src/index.tsx
+++ b/libs/gi/page-team/src/index.tsx
@@ -126,6 +126,7 @@ function Page({ teamId }: { teamId: string }) {
'sillyWisher_charNames',
'charNames_gen',
'page_character',
+ 'page_team',
])
useTitle(
@@ -136,11 +137,11 @@ function Page({ teamId }: { teamId: string }) {
silly ? 'sillyWisher_charNames' : 'charNames_gen'
}:${charKeyToLocGenderedCharKey(characterKey, gender)}`
)
- : t('Team Settings')
+ : t`page_team:teamSettings.tab.team`
const tabName = tab
? t(`page_character:tabs.${tab}`)
: characterKey
- ? t('Loadout/Build')
+ ? t`page_character:tabs.setting`
: tab
return tabName
? `${team.name} - ${charName} - ${tabName}`
diff --git a/libs/gi/page-teams/src/index.tsx b/libs/gi/page-teams/src/index.tsx
index 338c7c7106..05300f3a6e 100644
--- a/libs/gi/page-teams/src/index.tsx
+++ b/libs/gi/page-teams/src/index.tsx
@@ -37,10 +37,9 @@ import { teamFilterConfigs, teamSortConfigs, teamSortMap } from './TeamSort'
const columns = { xs: 1, sm: 2, md: 2, lg: 3, xl: 3 }
const numToShowMap = { xs: 6, sm: 12, md: 18, lg: 24, xl: 24 }
-// TODO: Translation
-
export default function PageTeams() {
const { t } = useTranslation([
+ 'page_team',
'page_teams',
// Always load these 2 so character names are loaded for searching/sorting
'sillyWisher_charNames',
@@ -70,10 +69,11 @@ export default function PageTeams() {
try {
const dataObj = JSON.parse(data)
if (!database.teams.import(dataObj))
- window.alert(`Data verification failed.`)
+ window.alert(t`importForm.error.verifi`)
onHideImport()
} catch (e) {
- window.alert(`Data Import failed. ${e}`)
+ window.alert(t`importForm.error.import` + `\n${e}`)
+
return
}
}
@@ -154,7 +154,7 @@ export default function PageTeams() {
onChange={(e: ChangeEvent) =>
setSearchTerm(e.target.value)
}
- label="Team Name"
+ label={t`searchLabel.team`}
// size="small"
sx={{ height: '100%', flexGrow: 1 }}
InputProps={{
@@ -178,20 +178,20 @@ export default function PageTeams() {
}>
- Add Team
+ {t`addTeamBtn`}
-
+
- Import a team in JSON form below.
+ {t`importForm.desc`}
setData(e.target.value)}
multiline
@@ -202,7 +202,7 @@ export default function PageTeams() {
disabled={!data}
onClick={importData}
>
- Import
+ {t`importForm.importBtn`}
@@ -213,7 +213,7 @@ export default function PageTeams() {
color="info"
startIcon={}
>
- Import Team
+ {t`importTeamBtn`}
-
-
- Weapon Filter
-
-
+ {t`weaponFilterTitle`}
{
}))
export default ExpandButton
-
-// TODO: Translation
export function EnemyExpandCard({ teamId }: { teamId: string }) {
+ const { t } = useTranslation('page_team')
const [expanded, setexpanded] = useState(false)
const toggle = useCallback(
() => setexpanded(!expanded),
@@ -69,7 +69,8 @@ export function EnemyExpandCard({ teamId }: { teamId: string }) {
color="success"
label={
- Enemy {enemyLevel}
+ {t`enemyEditor.enemyLevel`}
+ {enemyLevel}
}
/>
@@ -78,8 +79,12 @@ export function EnemyExpandCard({ teamId }: { teamId: string }) {
))}
- DEF Red. {enemyDefRed_}
- DEF Ignore {enemyDefIgn_}
+
+ {t('enemyEditor.defIgn', { value: enemyDefIgn_ })}
+
+
+ {t('enemyEditor.defRed', { value: enemyDefRed_ })}
+
- To get the specific resistance values of enemies, please visit the
- wiki.
+ {t`enemyEditor.announceBtn`}
@@ -220,7 +225,7 @@ export function EnemyEditor({
)
}
>
- Immunity
+ {t`enemyEditor.immunity`}
@@ -257,11 +262,7 @@ export function EnemyEditor({
/>
-
- Note: Genshin Impact halves resistance shred values below 0%. For the
- sake of calculations enter the RAW value and GO will do the rest.
- (e.g. 10% - 20% = -10%)
-
+ {t`enemyEditor.note`}
)
diff --git a/libs/gi/ui/src/components/build/BuildCard.tsx b/libs/gi/ui/src/components/build/BuildCard.tsx
index d6e33ab106..7a17e57a3f 100644
--- a/libs/gi/ui/src/components/build/BuildCard.tsx
+++ b/libs/gi/ui/src/components/build/BuildCard.tsx
@@ -15,8 +15,8 @@ import {
Typography,
} from '@mui/material'
import type { ReactNode } from 'react'
+import { useTranslation } from 'react-i18next'
-// TODO: Translation
export function BuildCard({
name,
description,
@@ -42,6 +42,7 @@ export function BuildCard({
onRemove?: () => void
hideFooter?: boolean
}) {
+ const { t } = useTranslation('build')
const clickableAreaContent = (
<>
Edit Build Settings}
+ title={{t`buildCardTip.edit`}}
placement="top"
arrow
>
@@ -99,7 +100,7 @@ export function BuildCard({
Copy to TC Builds}
+ title={{t`buildCardTip.copyTc`}}
placement="top"
arrow
>
@@ -113,7 +114,7 @@ export function BuildCard({
Duplicate Build}
+ title={{t`buildCardTip.duplicate`}}
placement="top"
arrow
>
@@ -127,7 +128,7 @@ export function BuildCard({
Equip Build}
+ title={{t`buildCardTip.equip`}}
placement="top"
arrow
>
@@ -141,7 +142,7 @@ export function BuildCard({
Delete Build}
+ title={{t`buildCardTip.delete`}}
placement="top"
arrow
>
diff --git a/libs/gi/ui/src/components/build/BuildDisplayItem.tsx b/libs/gi/ui/src/components/build/BuildDisplayItem.tsx
index a0589617f1..f6b6c148a5 100644
--- a/libs/gi/ui/src/components/build/BuildDisplayItem.tsx
+++ b/libs/gi/ui/src/components/build/BuildDisplayItem.tsx
@@ -81,7 +81,6 @@ type BuildDisplayItemProps = {
mainStatAssumptionLevel: number
}
-// TODO: Translation for build UI
//for displaying each artifact build
export const BuildDisplayItem = memo(function BuildDisplayItem({
label,
@@ -90,6 +89,7 @@ export const BuildDisplayItem = memo(function BuildDisplayItem({
disabled,
mainStatAssumptionLevel,
}: BuildDisplayItemProps) {
+ const { t } = useTranslation('page_character_optimize')
const {
loadoutDatum: { buildType, buildId },
teamChar: { buildIds = [] },
@@ -345,8 +345,9 @@ export const BuildDisplayItem = memo(function BuildDisplayItem({
{label}
- {/* TODO: Translation */}
- {currentlyEquipped && (Equipped)}
+ {currentlyEquipped && (
+ {t`buildDisplay.equippedBadge`}
+ )}
)}
@@ -361,8 +362,7 @@ export const BuildDisplayItem = memo(function BuildDisplayItem({
)?.name
}
- {/* TODO: Translation */}
- {isActiveBuild && (current build)}
+ {isActiveBuild && {t`buildDisplay.currentBadge`}}
{sameAsBuildIds.length > 1 && (
}
>
- Equip to Current Build
+ {t`buildDisplay.equipToCrr`}
{extraButtonsRight}
@@ -452,6 +452,7 @@ function CompareWeaponModal({
showWeapon: boolean
onClose: () => void
}) {
+ const { t } = useTranslation('page_character_optimize')
const database = useDatabase()
const diffCurrentWeap = oldId !== newId
@@ -479,12 +480,12 @@ function CompareWeaponModal({
- Old Weapon
+ {t`buildDisplay.oldWeapon`}
{oldId === 'tc' ? (
- TC Weapon
+ {t`buildDisplay.tcWeapon`}
) : (
@@ -501,7 +502,7 @@ function CompareWeaponModal({
- New Weapon
+ {t`buildDisplay.newWeapon`}
diff --git a/libs/gi/ui/src/components/build/EquipBuildModal.tsx b/libs/gi/ui/src/components/build/EquipBuildModal.tsx
index 31c6a49c84..8fbbfc6d1b 100644
--- a/libs/gi/ui/src/components/build/EquipBuildModal.tsx
+++ b/libs/gi/ui/src/components/build/EquipBuildModal.tsx
@@ -27,6 +27,7 @@ import {
} from '@mui/material'
import type { ReactNode } from 'react'
import { useContext, useMemo, useState } from 'react'
+import { Trans, useTranslation } from 'react-i18next'
import type { dataContextObj } from '../../context'
import { DataContext } from '../../context'
import { useCharData, useTeamData } from '../../hooks'
@@ -56,8 +57,8 @@ export function EquipBuildModal(props: Props & { show: boolean }) {
)
}
-/* TODO: Translation */
function Content(props: Props) {
+ const { t } = useTranslation('build')
const {
currentName,
currentWeaponId,
@@ -81,7 +82,8 @@ function Content(props: Props) {
const toEquip = () => {
if (copyCurrent) {
database.teamChars.newBuild(teamCharId, {
- name: name !== '' ? name : `Duplicate of ${currentName}`,
+ name:
+ name !== '' ? name : t('equipBuildModal.newName', { currentName }),
artifactIds: currentArtifactIds,
weaponId: currentWeaponId,
})
@@ -99,7 +101,10 @@ function Content(props: Props) {
- Confirm Equipment Changes for {currentName}
+
+ Confirm Equipment Changes for{' '}
+ {{ currentName } as any}
+
}
@@ -118,16 +123,15 @@ function Content(props: Props) {
}}
>
{/* Confirmation Message */}
-
- Do you want to make the changes shown below?
-
+ {t`equipBuildModal.desc`}
{teamCharId && (
- Copy the current equipment in {currentName} to
- a new build. Otherwise, they will be overwritten.
- >
+
+ Copy the current equipment in{' '}
+ {{ currentName } as any} to a new build.
+ Otherwise, they will be overwritten.
+
}
control={
setName(e.target.value)}
size="small"
@@ -157,10 +161,10 @@ function Content(props: Props) {
}}
>
- Cancel
+ {t`equipBuildModal.cancel`}
- Equip
+ {t`equipBuildModal.equip`}
{/* Active Build */}
diff --git a/libs/gi/ui/src/components/character/CharacterMultiAutocomplete.tsx b/libs/gi/ui/src/components/character/CharacterMultiAutocomplete.tsx
index 4bc727f1f8..f6fd9a8f7a 100644
--- a/libs/gi/ui/src/components/character/CharacterMultiAutocomplete.tsx
+++ b/libs/gi/ui/src/components/character/CharacterMultiAutocomplete.tsx
@@ -27,7 +27,12 @@ export function CharacterMultiAutocomplete({
setCharKey: (v: CharacterKey[]) => void
acProps?: Partial>
}) {
- const { t } = useTranslation(['sillyWisher_charNames', 'charNames_gen'])
+ const { t } = useTranslation([
+ 'page_team',
+ 'sillyWisher_charNames',
+ 'charNames_gen',
+ ])
+
const { silly } = useContext(SillyContext)
const database = useDatabase()
const { gender } = useDBMeta()
@@ -129,7 +134,7 @@ export function CharacterMultiAutocomplete({
return (
}>
void
}) {
+ const { t } = useTranslation('page_weapon')
const [show, onOpen, onClose] = useBoolState()
return (
{' '}
- {/* TODO translation */}
- {weaponTypeKey}
+ {t(`weaponType.${weaponTypeKey}`)}
diff --git a/libs/gi/ui/src/components/character/card/CharacterCardEquipmentRow.tsx b/libs/gi/ui/src/components/character/card/CharacterCardEquipmentRow.tsx
index 6f31599959..fe1dbeaa97 100644
--- a/libs/gi/ui/src/components/character/card/CharacterCardEquipmentRow.tsx
+++ b/libs/gi/ui/src/components/character/card/CharacterCardEquipmentRow.tsx
@@ -5,6 +5,7 @@ import { useDatabase } from '@genshin-optimizer/gi/db-ui'
import { input } from '@genshin-optimizer/gi/wr'
import { Box, Card, Grid, Typography } from '@mui/material'
import { useContext } from 'react'
+import { useTranslation } from 'react-i18next'
import { DataContext } from '../../../context'
import { ArtifactCardPico } from '../../artifact'
import { WeaponCardPico, WeaponCardPicoObj } from '../../weapon'
@@ -56,6 +57,7 @@ export function CharacterCardEquipmentRowTC({
}: {
weapon: ICachedWeapon
}) {
+ const { t } = useTranslation('page_weapon')
return (
@@ -74,9 +76,8 @@ export function CharacterCardEquipmentRowTC({
alignItems: 'center',
}}
>
- {/* TODO: Translation */}
- TC Build
+ {t`tcBuild`}
diff --git a/libs/gi/ui/src/components/character/card/CharacterCardStats.tsx b/libs/gi/ui/src/components/character/card/CharacterCardStats.tsx
index 2e1ce3ab2c..232f0e63c4 100644
--- a/libs/gi/ui/src/components/character/card/CharacterCardStats.tsx
+++ b/libs/gi/ui/src/components/character/card/CharacterCardStats.tsx
@@ -2,11 +2,13 @@ import type { CardBackgroundColor } from '@genshin-optimizer/common/ui'
import { input } from '@genshin-optimizer/gi/wr'
import { ListItem, Typography } from '@mui/material'
import { useContext } from 'react'
+import { useTranslation } from 'react-i18next'
import { DataContext } from '../../../context'
import { resolveInfo } from '../../../util'
import { FieldDisplayList, NodeFieldDisplay } from '../../FieldDisplay'
export function CharacterCardStats({ bgt }: { bgt?: CardBackgroundColor }) {
+ const { t } = useTranslation('page_character_optimize')
const { data } = useContext(DataContext)
const specialNode = data.get(input.special)
const { name, icon } = resolveInfo(specialNode.info)
@@ -18,7 +20,7 @@ export function CharacterCardStats({ bgt }: { bgt?: CardBackgroundColor }) {
{name && (
- Specialized:
+ {t`specialized`}
{icon}
{name}
diff --git a/libs/gi/ui/src/components/character/editor/BuildRealSimplified.tsx b/libs/gi/ui/src/components/character/editor/BuildRealSimplified.tsx
index 90fe2e2de2..50a48bc048 100644
--- a/libs/gi/ui/src/components/character/editor/BuildRealSimplified.tsx
+++ b/libs/gi/ui/src/components/character/editor/BuildRealSimplified.tsx
@@ -7,7 +7,6 @@ import { ArtifactCardNano } from '../../artifact'
import { BuildCard } from '../../build'
import { WeaponCardNano } from '../../weapon'
-// TODO: Translation
export function BuildRealSimplified({
buildId,
characterKey,
diff --git a/libs/gi/ui/src/components/character/editor/Content.tsx b/libs/gi/ui/src/components/character/editor/Content.tsx
index d78a9f4203..b9927ec3f1 100644
--- a/libs/gi/ui/src/components/character/editor/Content.tsx
+++ b/libs/gi/ui/src/components/character/editor/Content.tsx
@@ -20,7 +20,7 @@ import CloseIcon from '@mui/icons-material/Close'
import DeleteForeverIcon from '@mui/icons-material/DeleteForever'
import { Box, Button, Grid, IconButton, Typography } from '@mui/material'
import { useCallback, useContext, useEffect, useMemo } from 'react'
-import { useTranslation } from 'react-i18next'
+import { Trans, useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { DataContext, SillyContext } from '../../../context'
import { AddTeamInfo } from '../../AddTeamInfo'
@@ -202,6 +202,7 @@ function EquipmentSection() {
)
}
function InTeam() {
+ const { t } = useTranslation('page_character')
const navigate = useNavigate()
const {
@@ -243,12 +244,13 @@ function InTeam() {
})
navigate(`/teams/${teamId}`)
}
- // TODO: Translation
return (
- Team Loadouts with{' '}
-
+
+ Team Loadouts with{' '}
+
+
{!Object.values(loadoutTeamMap).length && }
@@ -267,7 +269,7 @@ function InTeam() {
variant="outlined"
sx={{ backgroundColor: 'contentLight.main' }}
>
- Add new Loadout+Team
+ {t`charContentModal.addLoAndTeam`}
diff --git a/libs/gi/ui/src/components/character/editor/LoadoutCard.tsx b/libs/gi/ui/src/components/character/editor/LoadoutCard.tsx
index 140b58403d..5677221ad8 100644
--- a/libs/gi/ui/src/components/character/editor/LoadoutCard.tsx
+++ b/libs/gi/ui/src/components/character/editor/LoadoutCard.tsx
@@ -10,6 +10,7 @@ import {
Divider,
Grid,
} from '@mui/material'
+import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { TeamCard } from '../../team'
import { LoadoutEditor } from './LoadoutEditor'
@@ -19,7 +20,6 @@ const columns = {
md: 2,
} as const
-// TODO: Translation
export function LoadoutCard({
teamCharId,
teamIds,
@@ -27,6 +27,7 @@ export function LoadoutCard({
teamCharId: string
teamIds: string[]
}) {
+ const { t } = useTranslation('page_character')
const navigate = useNavigate()
const database = useDatabase()
const onAddTeam = (teamCharId: string) => {
@@ -71,7 +72,7 @@ export function LoadoutCard({
color="info"
startIcon={}
>
- Add new Team
+ {t`charContentModal.addTeam`}
diff --git a/libs/gi/ui/src/components/character/editor/LoadoutEditor.tsx b/libs/gi/ui/src/components/character/editor/LoadoutEditor.tsx
index 7861034aa9..c784cc7130 100644
--- a/libs/gi/ui/src/components/character/editor/LoadoutEditor.tsx
+++ b/libs/gi/ui/src/components/character/editor/LoadoutEditor.tsx
@@ -34,6 +34,7 @@ import {
Typography,
} from '@mui/material'
import { useMemo } from 'react'
+import { useTranslation } from 'react-i18next'
import { useNavigate } from 'react-router-dom'
import { OptimizationIcon } from '../../../consts'
import { DocumentDisplay } from '../../DocumentDisplay'
@@ -56,6 +57,7 @@ export function LoadoutEditor({
teamCharId: string
teamIds: string[]
}) {
+ const { t } = useTranslation('loadout')
const [showRemoval, onShowRemoval, onHideRemoval] = useBoolState()
const navigate = useNavigate()
const database = useDatabase()
@@ -122,14 +124,14 @@ export function LoadoutEditor({
database.teamChars.set(teamCharId, { name })}
/>
database.teamChars.set(teamCharId, { description })
@@ -146,7 +148,7 @@ export function LoadoutEditor({
fullWidth
startIcon={}
>
- Duplicate Loadout
+ {t`loadoutEditor.dupBtn`}
@@ -164,7 +166,7 @@ export function LoadoutEditor({
color="error"
onClick={onShowRemoval}
>
- Delete Loadout
+ {t`loadoutEditor.delBtn`}
@@ -190,7 +192,7 @@ export function LoadoutEditor({
}}
>
- Optimization Target
+ {t`loadoutEditor.optTarget`}
}
/>
@@ -218,7 +220,8 @@ export function LoadoutEditor({
- Conditionals: {conditionalCount}
+ {t`loadoutEditor.conditionals`}
+ {conditionalCount}
@@ -231,7 +234,7 @@ export function LoadoutEditor({
title={
- Builds
+ {t`loadoutEditor.builds`}
}
/>
@@ -267,7 +270,7 @@ export function LoadoutEditor({
title={
- Teams
+ {t`loadoutEditor.teams`}
}
/>
@@ -295,7 +298,7 @@ export function LoadoutEditor({
color="info"
startIcon={}
>
- Add new Team
+ {t`loadoutEditor.addNewTeam`}
@@ -310,6 +313,7 @@ function BonusStatsCard({
}: {
bonusStats: TeamCharacter['bonusStats']
}) {
+ const { t } = useTranslation('loadout')
return (
- Bonus Stats
+ {t`loadoutEditor.bonusStats`}
}
titleTypographyProps={{ variant: 'h6' }}
@@ -348,6 +352,7 @@ function MultiTargetCard({
}: {
customMultiTargets: TeamCharacter['customMultiTargets']
}) {
+ const { t } = useTranslation('loadout')
return (
- Custom multi-targets
+ {t`loadoutEditor.mltTargets`}
}
titleTypographyProps={{ variant: 'h6' }}
diff --git a/libs/gi/ui/src/components/character/editor/LoadoutHeaderContent.tsx b/libs/gi/ui/src/components/character/editor/LoadoutHeaderContent.tsx
index 4038d9dc33..dc4b39bbd2 100644
--- a/libs/gi/ui/src/components/character/editor/LoadoutHeaderContent.tsx
+++ b/libs/gi/ui/src/components/character/editor/LoadoutHeaderContent.tsx
@@ -7,6 +7,7 @@ import PersonIcon from '@mui/icons-material/Person'
import SettingsIcon from '@mui/icons-material/Settings'
import { Box, CardContent, Typography } from '@mui/material'
import type { ReactNode } from 'react'
+import { useTranslation } from 'react-i18next'
import { OptimizationIcon } from '../../../consts'
import { OptimizationTargetDisplay } from './OptimizationTargetDisplay'
export function LoadoutHeaderContent({
@@ -18,6 +19,7 @@ export function LoadoutHeaderContent({
showSetting?: boolean
children?: ReactNode
}) {
+ const { t } = useTranslation('loadout')
const database = useDatabase()
const {
name,
@@ -46,26 +48,29 @@ export function LoadoutHeaderContent({
- Builds: {buildIds.length}
+ {t`loadoutHeader.builds`}
+ {buildIds.length}
- TC Builds: {buildTcIds.length}
+ {t`loadoutHeader.tcBuilds`}
+ {buildTcIds.length}
- Custom multi-targets: {customMultiTargets.length}
+ {t`loadoutHeader.mltTargets`}
+ {customMultiTargets.length}
{optimizationTarget && (
- Optimization Target:
+ {t`loadoutHeader.optTarget`}
void
conditionalCount: number
}) {
+ const { t } = useTranslation('loadout')
const database = useDatabase()
const {
name,
@@ -60,7 +62,9 @@ export function RemoveLoadout({
- Delete Loadout: {name}?
+
+ Delete Loadout: {{ name } as any}?
+
}
action={
@@ -76,14 +80,13 @@ export function RemoveLoadout({
{description}
)}
-
- Deleting the Loadout will also delete the following data:
-
+ {t`loadoutDelModal.desc`}
{!!buildIds.length && (
- All saved builds: {buildIds.length}{' '}
+ {t`loadoutDelModal.builds`}
+ {buildIds.length}{' '}
@@ -112,7 +115,8 @@ export function RemoveLoadout({
{!!buildTcIds.length && (
- All saved TC builds: {buildTcIds.length}{' '}
+ {t`loadoutDelModal.tcBuilds`}
+ {buildTcIds.length}{' '}
@@ -141,7 +145,8 @@ export function RemoveLoadout({
{!!customMultiTargets.length && (
- All Custom Multi-targets: {customMultiTargets.length}{' '}
+ {t`loadoutDelModal.mTargets`}
+ {customMultiTargets.length}{' '}
@@ -169,24 +174,25 @@ export function RemoveLoadout({
{!!Object.keys(bonusStats).length && (
- Bonus stats: {Object.keys(bonusStats).length}
+ {t`loadoutDelModal.bonus`}
+ {Object.keys(bonusStats).length}
)}
{!!conditionalCount && (
- Conditionals: {conditionalCount}
+ {t`loadoutDelModal.condi`}
+ {conditionalCount}
)}
- Optimization Configuration
+ {t`loadoutDelModal.optConfig`}
{!!teamIds.length && (
- Any teams with this loadout will have this loadout removed
- from the team. Teams will not be deleted. Teams affected:{' '}
+ {t`loadoutDelModal.affected`}
{teamIds.length}
@@ -218,14 +224,14 @@ export function RemoveLoadout({
} color="secondary" onClick={onHide}>
- Cancel
+ {t`loadoutDelModal.cancel`}
}
color="error"
onClick={onDeleteLoadout}
>
- Delete
+ {t`loadoutDelModal.delete`}
diff --git a/libs/gi/ui/src/components/loadout/LoadoutInfoAlert.tsx b/libs/gi/ui/src/components/loadout/LoadoutInfoAlert.tsx
index 84d14f706b..2812dc0a1e 100644
--- a/libs/gi/ui/src/components/loadout/LoadoutInfoAlert.tsx
+++ b/libs/gi/ui/src/components/loadout/LoadoutInfoAlert.tsx
@@ -1,12 +1,16 @@
import { Alert } from '@mui/material'
+import { Trans, useTranslation } from 'react-i18next'
-// TODO: Translation
export function LoadoutInfoAlert() {
+ const { t } = useTranslation('loadout')
return (
- Loadouts provides character context data, including bonus
- stats, conditionals, multi-targets, optimization config, and stores
- builds. A single Loadout can be used for many teams.
+
+ Loadouts provides character context data, including
+ bonus stats, conditionals, multi-targets, optimization config, and
+ stores builds. A single Loadout can be used for many
+ teams.
+
)
}
diff --git a/libs/gi/ui/src/components/team/TeamCard.tsx b/libs/gi/ui/src/components/team/TeamCard.tsx
index 4648010775..987c57ef22 100644
--- a/libs/gi/ui/src/components/team/TeamCard.tsx
+++ b/libs/gi/ui/src/components/team/TeamCard.tsx
@@ -55,8 +55,6 @@ import { getBuildTcArtifactData, iconAsset } from '../../util'
import { ArtifactSlotName } from '../artifact'
import { TeamDelModal } from './TeamDelModal'
-// TODO: Translation
-
export function TeamCard({
teamId,
onClick,
diff --git a/libs/gi/ui/src/components/team/TeamDelModal.tsx b/libs/gi/ui/src/components/team/TeamDelModal.tsx
index 5bf1c973ee..00dce246a9 100644
--- a/libs/gi/ui/src/components/team/TeamDelModal.tsx
+++ b/libs/gi/ui/src/components/team/TeamDelModal.tsx
@@ -23,6 +23,7 @@ import {
Typography,
} from '@mui/material'
import { useMemo, useState } from 'react'
+import { Trans, useTranslation } from 'react-i18next'
import type { dataContextObj } from '../../context/DataContext'
import { DataContext } from '../../context/DataContext'
import { useCharData } from '../../hooks/useCharData'
@@ -38,6 +39,7 @@ export function TeamDelModal({
onHide: () => void
onDel: () => void
}) {
+ const { t } = useTranslation('page_team')
const database = useDatabase()
const team = useTeam(teamId)!
const { name, description, loadoutData } = team
@@ -78,7 +80,7 @@ export function TeamDelModal({
alignItems: 'center',
}}
>
- Delete Team:
+ {t`teamDelModal.teamName`}
{name}
{description && (
@@ -96,9 +98,11 @@ export function TeamDelModal({
- Removing the team will remove: resonance buffs, and enemy configs
- stored in the team. Loadouts that are only in this team are also
- selected by default for deletion.
+
+ Removing the team will remove: resonance buffs, and enemy configs
+ stored in the team. Loadouts that are only in this team are also
+ selected by default for deletion.
+
{loadoutData.map((loadoutDatum, i) =>
loadoutDatum ? (
@@ -119,7 +123,7 @@ export function TeamDelModal({
startIcon={}
onClick={onDelete}
>
- Delete
+ {t`teamDelModal.delBtn`}
@@ -137,6 +141,7 @@ function LoadoutDisplay({
onClick: () => void
inTeams: Team[]
}) {
+ const { t } = useTranslation('page_team')
const teamChar = useTeamChar(teamCharId)!
const { key: characterKey } = teamChar
const teamData = useCharData(characterKey)
@@ -162,8 +167,8 @@ function LoadoutDisplay({
{inTeams.length === 1
- ? 'Only in current team'
- : `In ${inTeams.length} teams`}
+ ? t`teamDelModal.onlyCrrTeam`
+ : t('teamDelModal.usingMltTeams', { count: inTeams.length })}
diff --git a/libs/gi/ui/src/components/team/TeamInfoAlert.tsx b/libs/gi/ui/src/components/team/TeamInfoAlert.tsx
index 021d2a8707..9ce789cd7b 100644
--- a/libs/gi/ui/src/components/team/TeamInfoAlert.tsx
+++ b/libs/gi/ui/src/components/team/TeamInfoAlert.tsx
@@ -1,12 +1,15 @@
import { Alert } from '@mui/material'
+import { Trans, useTranslation } from 'react-i18next'
-// TODO: Translation
export function TeamInfoAlert() {
+ const { t } = useTranslation('page_team')
return (
- Teams are a container for 4 character loadouts. It
- provides a way for characters to apply team buffs, and configuration of
- enemy stats. Loadouts can be shared between teams.
+
+ Teams are a container for 4 character loadouts. It
+ provides a way for characters to apply team buffs, and configuration of
+ enemy stats. Loadouts can be shared between teams.
+
)
}
diff --git a/libs/gi/ui/src/components/weapon/WeaponCard.tsx b/libs/gi/ui/src/components/weapon/WeaponCard.tsx
index 7a1a92064e..49f985b7b1 100644
--- a/libs/gi/ui/src/components/weapon/WeaponCard.tsx
+++ b/libs/gi/ui/src/components/weapon/WeaponCard.tsx
@@ -32,7 +32,7 @@ import {
} from '@mui/material'
import type { ReactNode } from 'react'
import { Suspense, useCallback, useMemo } from 'react'
-import { useTranslation } from 'react-i18next'
+import { Trans, useTranslation } from 'react-i18next'
import { getCalcDisplay, resolveInfo } from '../../util'
import { LocationAutocomplete, LocationName } from '../character'
import { WeaponName } from './WeaponTrans'
@@ -167,7 +167,9 @@ export function WeaponCardObj({
/{ascensionMaxLevel[ascension]}
- Refinement {refinement}
+
+ Refinement {{ rank: refinement } as any}
+