Improves i18n and allows for toggling to simplified Chinese (#632)

This commit is contained in:
Chris Anderson 2025-02-25 22:45:55 -06:00 committed by GitHub
parent eac555ca58
commit 4d1d7d1e53
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 35 additions and 15 deletions

View file

@ -215,11 +215,15 @@
"options": "Options",
"pending": "Pending",
"period": "Period",
"performance": "Performance",
"phone": "Phone",
"plain_text": "Plain Text",
"preheader": "Preheader",
"preview": "Preview",
"project": "Project",
"projects": "Projects",
"projects_all": "All Projects",
"projects_description": "Projects are isolated workspaces with their own sets of users, events, lists, campaigns, and journeys.",
"project_settings_saved": "Project settings saved!",
"provider": "Provider",
"publish": "Publish",
@ -233,6 +237,7 @@
"rebuild_path_suggestions": "Rebuild Path Suggestions",
"rebuild_path_suggestions_desc": "Would you like to recreate all of the event and user data autocomplete paths used for creating rules?",
"rebuild_path_suggestions_success": "Path suggestions are rebuilding. This might take a few minutes depending on how many users and events you have.",
"recently_viewed": "Recently Viewed",
"remove": "Remove",
"remove_locale_warning": "Are you sure you want to delete this locale? The template cannot be recovered.",
"reply_to": "Reply To",

View file

@ -215,11 +215,15 @@
"options": "Opciones",
"pending": "Pendiente",
"period": "Período",
"performance": "Rendimiento",
"phone": "Teléfono",
"plain_text": "Texto sin formato",
"preheader": "Preencabezado",
"preview": "Previsualizar",
"project": "Proyecto",
"projects": "Projectos",
"projects_all": "Todos Projects",
"projects_description": "Los proyectos son espacios de trabajo aislados con sus propios usuarios, eventos, listas, campañas y caminos.",
"project_settings_saved": "¡Ajustes del proyecto guardados!",
"provider": "Proveedor",
"publish": "Publicar",
@ -233,6 +237,7 @@
"rebuild_path_suggestions": "Reconstruir las Sugerencias de Ruta",
"rebuild_path_suggestions_desc": "¿Le gustaría recrear todas las rutas de autocompletado de datos de eventos y usuarios utilizadas para crear reglas?",
"rebuild_path_suggestions_success": "Las sugerencias de ruta se están reconstruyendo. Esto puede tardar unos minutos dependiendo de cuántos usuarios y eventos tengas.",
"recently_viewed": "Visto Recientemente",
"remove": "Eliminar",
"remove_locale_warning": "¿Está seguro de que desea eliminar esta configuración regional? La plantilla no se puede recuperar.",
"reply_to": "Responder a",

View file

@ -215,11 +215,15 @@
"options": "选项",
"pending": "待处理",
"period": "周期",
"performance": "表现",
"phone": "电话",
"plain_text": "纯文本",
"preheader": "预标题",
"preview": "预览",
"project": "项目",
"projects": "项目",
"projects_all": "所有项目",
"projects_description": "项目是独立的工作区,拥有自己的用户、事件、列表、活动和旅程。",
"project_settings_saved": "项目设置已保存!",
"provider": "提供商",
"publish": "发布",
@ -233,6 +237,7 @@
"rebuild_path_suggestions": "重建路径建议",
"rebuild_path_suggestions_desc": "您想重新创建用于创建规则的所有事件和用户数据自动完成路径吗?",
"rebuild_path_suggestions_success": "正在重建路径建议。这可能需要几分钟,具体取决于您有多少用户和事件。",
"recently_viewed": "最近浏览",
"remove": "移除",
"remove_locale_warning": "您确定要删除此地区吗?模板无法恢复。",
"reply_to": "回复至",

View file

@ -89,8 +89,8 @@ export default function Sidebar({ children, links, prepend, append }: PropsWithC
{children}
</main>
<Modal open={isLanguageOpen} onClose={() => setIsLanguageOpen(false)} title={'Language'}>
<RadioInput label={t('language')} options={[{ label: 'English', key: 'en' }, { label: 'Espańol', key: 'es' }]} value={i18n.language} onChange={(value) => {
<Modal open={isLanguageOpen} onClose={() => setIsLanguageOpen(false)} title={t('language')}>
<RadioInput label={t('language')} options={[{ label: 'English', key: 'en' }, { label: 'Español', key: 'es' }, { label: '简体中文', key: 'zh' }]} value={i18n.language} onChange={(value) => {
setPreferences({ ...preferences, lang: value })
}} />
</Modal>

View file

@ -6,6 +6,7 @@ import { checkOrganizationRole } from '../../utils'
import { StatefulLoaderContextProvider } from '../LoaderContextProvider'
import { OrganizationRole } from '../../types'
import { Outlet } from 'react-router-dom'
import { Translation } from 'react-i18next'
type OrganizationLink = SidebarLink & { minRole?: OrganizationRole }
interface OrganizationProps {
@ -18,27 +19,27 @@ export default function Organization({ filter }: OrganizationProps) {
{
key: 'projects',
to: 'projects',
children: 'Projects',
children: <Translation>{ t => t('projects') }</Translation>,
icon: <ProjectIcon />,
},
{
key: 'admins',
to: 'admins',
children: 'Admins',
children: <Translation>{ t => t('admins') }</Translation>,
icon: <UsersIcon />,
minRole: 'admin',
},
{
key: 'performance',
to: 'performance',
children: 'Performance',
children: <Translation>{ t => t('performance') }</Translation>,
icon: <PerformanceIcon />,
minRole: 'admin',
},
{
key: 'settings',
to: 'settings',
children: 'Settings',
children: <Translation>{ t => t('settings') }</Translation>,
icon: <SettingsIcon />,
minRole: 'admin',
},

View file

@ -136,7 +136,7 @@ export default function Performance() {
return (
<PageContent
title="Performance"
title={t('performance')}
desc="View queue throughput for your project."
>
<Heading size="h3" title="Queue" />

View file

@ -8,9 +8,11 @@ import Heading from '../../ui/Heading'
import api from '../../api'
import { toast } from 'react-hot-toast/headless'
import { Button } from '../../ui'
import { useTranslation } from 'react-i18next'
export default function Settings() {
const profile = useContext(AdminContext)
const { t } = useTranslation()
const [organization] = useContext(OrganizationContext)
const deleteOrganization = async () => {
if (confirm('Are you sure you want to delete this organization?')) {
@ -24,7 +26,7 @@ export default function Settings() {
return (
<>
<PageContent title="Settings">
<PageContent title={t('settings')}>
<FormWrapper<Organization>
defaultValues={organization}
disabled={!owner}
@ -36,7 +38,7 @@ export default function Settings() {
submitLabel="Save Settings"
>
{form => <>
<Heading size="h3" title="General" />
<Heading size="h3" title={t('general')} />
<TextInput.Field
form={form}
disabled={!owner}

View file

@ -12,9 +12,11 @@ import logoUrl from '../../assets/parcelvoylogo.png'
import { PlusIcon } from '../../ui/icons'
import Modal from '../../ui/Modal'
import ProjectForm from './ProjectForm'
import { useTranslation } from 'react-i18next'
export function Projects() {
const navigate = useNavigate()
const { t } = useTranslation()
const [preferences] = useContext(PreferencesContext)
const [projects] = useResolver(api.projects.all)
const recents = useMemo(() => {
@ -44,22 +46,22 @@ export function Projects() {
return (
<PageContent
title="Projects"
desc="Projects are isolated workspaces with their own sets of users, events, lists, campaigns, and journeys."
title={t('projects')}
desc={t('projects_description')}
actions={
<Button
variant="primary"
icon={<PlusIcon />}
onClick={() => setOpen(true)}
>
{'Create Project'}
{t('create_project')}
</Button>
}
>
{
!!recents?.length && (
<>
<h3>Recently Visited</h3>
<h3>{t('recently_viewed')}</h3>
<TileGrid>
{
recents.map(({ project, when }) => (
@ -77,7 +79,7 @@ export function Projects() {
</>
)
}
<h3>All Projects</h3>
<h3>{t('projects_all')}</h3>
<TileGrid>
{
projects?.map(project => (
@ -95,7 +97,7 @@ export function Projects() {
<Modal
open={open}
onClose={setOpen}
title="Create Project"
title={t('create_project')}
size="regular"
>
<ProjectForm