Agent产品的国际化架构:i18n、时区处理与内容本地化的工程实践
Agent产品的国际化架构i18n、时区处理与内容本地化的工程实践一、引言AI Agent产品出海时国际化是第一道技术门槛。不是翻译几个词条就算国际化。时区混乱导致报表错位本地化不足导致用户流失。这些问题在产品上线后的修复成本远超提前规划。国际化架构需要覆盖三个层面文本翻译(i18n)、时间处理(时区)、内容适配(本地化)。本文给出一个生产级的实现方案。行业案例某Agent产品的多语言支持实践一家做AI客服Agent的公司产品原来只支持中文。2024年决定支持英文和日文。第一版做法用GPT-4o实时翻译所有Agent输出。用户输入英文Agent用英文回复。用户输入日文Agent用日文回复。上线后发现英文回复质量可以用户接受度约75%。日文回复质量差特别是敬语使用不准确。日本用户接受度约48%。问题实时翻译的日文输出语气和敬语级别不稳定。日本企业客户对语气敏感不接受。修复方案英文继续用GPT-4o实时翻译。英文容错率高。日文建立人工翻译的提示词库。针对客服场景预翻译了200个高频回复模板。Agent优先用模板回复模板覆盖不到的才实时翻译。系统消息如正在处理全部人工翻译不用实时翻译。修复后日本用户接受度提升到71%。数据说明AI翻译适合容错率高的语言英文不适合容错率低的语言日文、阿拉伯文。关键场景系统消息、法律文本必须人工翻译。二、原理三层国际化架构三层架构的设计逻辑展示层根据用户设置渲染界面。服务层核心转换逻辑。AI层LLM自动感知用户语言生成内容。核心原则存储用UTC展示按用户时区。三、代码国际化核心模块from __future__ import annotations import json import os from datetime import datetime, timezone, timedelta from typing import Dict, Optional, Any from dataclasses import dataclass from zoneinfo import ZoneInfo import gettext # 1. i18n 翻译引擎 class I18nEngine: 国际化翻译引擎 SUPPORTED_LANGUAGES { zh-CN: 简体中文, zh-TW: 繁體中文, en-US: English, ja-JP: 日本語, ko-KR: 한국어, } def __init__(self, translations_dir: str ./locales): self.translations_dir translations_dir self._translations: Dict[str, Dict[str, str]] {} self._load_all() def _load_all(self): 加载所有翻译文件 for lang in self.SUPPORTED_LANGUAGES: path os.path.join( self.translations_dir, f{lang}.json ) if os.path.exists(path): with open(path, r, encodingutf-8) as f: self._translations[lang] json.load(f) def translate( self, key: str, locale: str zh-CN, **kwargs ) - str: 翻译并支持变量插值 locale locale if locale in self._translations else zh-CN text self._translations.get(locale, {}).get(key, key) if kwargs: text text.format(**kwargs) return text def add_translation(self, key: str, translations: Dict[str, str]): 动态添加翻译 for lang, text in translations.items(): if lang not in self._translations: self._translations[lang] {} self._translations[lang][key] text # 2. 时区处理引擎 class TimezoneEngine: 时区处理引擎 # 常用时区映射 TIMEZONE_MAP { Asia/Shanghai: 08:00, Asia/Tokyo: 09:00, America/New_York: -05:00, America/Los_Angeles: -08:00, Europe/London: 01:00, } staticmethod def utc_now() - datetime: 获取当前UTC时间 return datetime.now(timezone.utc) staticmethod def to_user_tz( dt: datetime, tz_name: str Asia/Shanghai ) - datetime: UTC时间转换为用户时区 if dt.tzinfo is None: dt dt.replace(tzinfotimezone.utc) return dt.astimezone(ZoneInfo(tz_name)) staticmethod def from_user_tz( dt_str: str, tz_name: str Asia/Shanghai, fmt: str %Y-%m-%d %H:%M ) - datetime: 用户输入时间转为UTC user_tz ZoneInfo(tz_name) dt datetime.strptime(dt_str, fmt) dt dt.replace(tzinfouser_tz) return dt.astimezone(timezone.utc) staticmethod def format_for_user( dt: datetime, tz_name: str Asia/Shanghai, fmt: str %Y-%m-%d %H:%M ) - str: 格式化为用户时区的可读时间 local_dt TimezoneEngine.to_user_tz(dt, tz_name) return local_dt.strftime(fmt) staticmethod def relative_time(dt: datetime, tz_name: str Asia/Shanghai) - str: 相对时间描述 local_dt TimezoneEngine.to_user_tz(dt, tz_name) now TimezoneEngine.utc_now() now_local TimezoneEngine.to_user_tz(now, tz_name) diff now_local - local_dt if diff timedelta(minutes1): return 刚刚 elif diff timedelta(hours1): return f{diff.seconds // 60}分钟前 elif diff timedelta(days1): return f{diff.seconds // 3600}小时前 elif diff timedelta(days30): return f{diff.days}天前 return local_dt.strftime(%m月%d日) staticmethod def business_hours(tz_name: str) - tuple: 判断指定时区是否在工作时间 now_utc TimezoneEngine.utc_now() local TimezoneEngine.to_user_tz(now_utc, tz_name) return 9 local.hour 18 and local.weekday() 5 # 3. 内容本地化引擎 class ContentLocalizer: 内容本地化引擎 # 地区配置 REGION_CONFIG { CN: { currency: CNY, currency_symbol: ¥, date_format: %Y-%m-%d, number_format: {thousands_sep: ,, decimal_sep: .}, first_day_of_week: 0, # 周日 }, US: { currency: USD, currency_symbol: $, date_format: %m/%d/%Y, number_format: {thousands_sep: ,, decimal_sep: .}, first_day_of_week: 6, # 周六 }, JP: { currency: JPY, currency_symbol: ¥, date_format: %Y年%m月%d日, number_format: {thousands_sep: ,, decimal_sep: .}, first_day_of_week: 0, }, } classmethod def format_price(cls, amount: float, region: str CN) - str: 价格本地化 config cls.REGION_CONFIG.get(region, cls.REGION_CONFIG[CN]) symbol config[currency_symbol] if region JP: return f{symbol}{int(amount):,} return f{symbol}{amount:,.2f} classmethod def format_number(cls, value: float, region: str CN) - str: 数字本地化 config cls.REGION_CONFIG.get(region, cls.REGION_CONFIG[CN]) fmt config[number_format] return f{value:,.0f} if value int(value) else f{value:,.2f} classmethod def system_prompt_for_locale(cls, locale: str) - str: 根据语言生成系统提示词片段 prompts { zh-CN: 请用简体中文回复。, en-US: Please respond in English., ja-JP: 日本語で返信してください。, } return prompts.get(locale, prompts[zh-CN]) # 4. 翻译文件示例 (locales/zh-CN.json) { welcome: 欢迎使用{name}, task_completed: 任务已完成, error_network: 网络连接失败请检查网络, settings_language: 语言设置, settings_timezone: 时区设置, billing_monthly: 月付 {price} } # 使用示例 dataclass class UserPreferences: locale: str zh-CN timezone: str Asia/Shanghai region: str CN class InternationalizationService: 国际化服务统一入口 def __init__(self, translations_dir: str ./locales): self.i18n I18nEngine(translations_dir) self.tz TimezoneEngine() self.localizer ContentLocalizer() def render_message( self, key: str, user: UserPreferences, **kwargs ) - str: 渲染国际化消息 return self.i18n.translate(key, user.locale, **kwargs) def render_time( self, dt: datetime, user: UserPreferences ) - str: 渲染用户时区时间 return self.tz.format_for_user(dt, user.timezone) def render_price( self, amount: float, user: UserPreferences ) - str: 渲染本地化价格 return self.localizer.format_price(amount, user.region) if __name__ __main__: service InternationalizationService() # 中国用户 user_cn UserPreferences() print(service.render_message(welcome, user_cn, name张三)) print(service.render_price(99.9, user_cn)) # 美国用户 user_us UserPreferences( localeen-US, timezoneAmerica/New_York, regionUS ) print(service.render_message(welcome, user_us, nameJohn)) print(service.render_price(14.99, user_us))关键设计翻译文件JSON格式支持变量插值{name}。UTC存储铁律所有时间存UTC展示时转换。ZoneInfo标准库无需第三方依赖。地区配置表货币、日期、数字格式集中管理。四、权衡国际化深度决策前期投入 vs 后期补救。国际化要在产品初期就做架构设计。初期花1-2周搭建框架避免后期全部重写。翻译文件管理。JSON文件适合早期超过500条翻译就需要翻译管理平台如Lokalise、Crowdin。AI翻译 vs 人工翻译。LLM翻译速度飞快但专业术语准确率只有85-90%。核心界面建议人工校对。时区带来的复杂度。跨时区协作用户的日程、统计报表都需要额外处理。建议从两个时区开始覆盖逐步扩展。取舍决策国际化深度的选择框架国际化做到什么深度根据目标市场和产品特性决定目标市场判断英语市场容错率高AI翻译质量足够。国际化成本低。日语、韩语、阿拉伯语市场容错率低需要人工校对。国际化成本高。欧盟市场有GDPR合规要求。数据不能随便出境。国际化不仅是翻译还有合规。产品特性判断面向消费者的产品UI翻译用AI翻译人工校对内容翻译用AI实时翻译。面向企业的产品所有翻译都需要人工校对。企业客户对语言准确度要求高。有合规要求的产品金融、医疗法律文书必须人工翻译不能靠AI。投入优先级第一步支持英文覆盖最多用户。第二步支持目标市场的本地语言如做日本市场就支持日文。第三步根据用户反馈逐步完善翻译质量。不建议一次性支持10种语言。翻译质量不高维护成本高。不如先支持2-3种语言把质量做好。决策输出根据目标市场和产品特性选择国际化的深度和优先级。不要为了支持多语言而支持多语言要为服务好目标市场而做国际化。五、总结国际化不是可选项是AI产品出海的必修课。三层架构涵盖了i18n、时区和内容本地化的核心需求。本文代码零外部依赖可直接集成。落地建议先用zh-CN和en-US两个语言验证框架稳定后逐步增加。时区先覆盖东亚和北美这两个区域的用户占比最高。翻译文件单独管理方便后续接入翻译平台。

相关新闻

最新新闻

日新闻

周新闻

月新闻