- #133
- #132
- #131
- #130
i18n 实作必须留意不同语言语序与逻辑的差异
近期翻新了一下我自制的个人网站模板:Letter,看到让我有点在意的地方是下面这段:
{t('Hero-1', { name: t('Me-1') })}<br />{t('Hero-2', { number: '100' })} <a class="highlight" href={`https://www.webdong.dev/${Astro.currentLocale}/post/`}>{t('Hero-3')}</a> {t('Hero-4')} {t('Hero-5', {number: '800'})}{t('Hero-6')} <a class="highlight" href={getRelativeLocaleUrl(Astro.currentLocale || defaultLocale, '/work')}>{t('Hero-7')}</a> {t('Hero-8')}"Hero-1": "哈啰,我是{name}","Hero-2": "我撰写超过 {number} 篇","Hero-3": "技术文章","Hero-4": "纪录与传达知识","Hero-5": "帮助 {number} 位以上开发者消除他们的疑惑。","Hero-6": "可以观赏","Hero-7": "作品集","Hero-8": "了解我是如何解决真实世界问题的。",真的有点丑且光是想到要替换就很头痛,特别是换个语序差别大一点的语言根本没办法运作,所以最好这样写,根据「概念而非语序或样式去拆分」:
<Fragment set:html={t('Hero-2', {articles: '100',articlesLink: `<a class="highlight" href="https://www.webdong.dev/${Astro.currentLocale}/post/">${t('Hero-ArticlesLink')}</a>`,developers: '800'})} /><Fragment set:html={t('Hero-3', {portfolioLink: `<a class="highlight" href="${getRelativeLocaleUrl(Astro.currentLocale || defaultLocale, '/work')}">${t('Hero-PortfolioLink')}</a>`})} />"Hero-2": "我撰写超过 {articles} 篇{articlesLink}纪录与传达知识,帮助 {developers} 位以上开发者消除他们的疑惑。","Hero-3": "可以观赏{portfolioLink}了解我是如何解决真实世界问题的。","Hero-ArticlesLink": "技术文章","Hero-PortfolioLink": "作品集",当时这么做应该是想要保持翻译文件单纯,不要又掺杂样式或 Markup 结构,还可能会有 XSS 的麻烦问题,不过事后权衡下来大多时候直接写进翻译内是更省事⋯⋯更何况我可以直接用参数的方式在外面组合进去。
t是自制的 i18n 翻译工具,应该大多 i18n 套件都有类似 placeholder 的方式去处理翻译。 - #129
- #128
- #127
- #126
- #125
- #124
- #123
- #122
- #121
- #120
- #119
- #118
- #117
- #116
- #115
- #114
- #113
- #112
- #111
- #110
- #109
- #108
- #107
- #106
- #105
- #104
- #103
- #102
- #101
- #100
- #99
- #98
- #97
- #96
- #95
- #94
- #93
- #92
- #91
- #90
- #89
- #88
- #87
- #86
- #85
- #84
- #83
- #82
- #81
- #80
- #79
- #78
- #77
- #76
- #75
- #74
- #73
- #72
- #71
- #70
- #69
- #68
- #67
- #66
- #65
- #64
- #63
- #62
- #61
- #60
- #59
- #58
- #57
- #56
- #55
- #54
- #53
- #52
- #51
- #50
- #49
- #48
- #47
- #46
- #45
- #44
- #43
- #42
- #41
- #40
- #39
- #38
- #37
- #36
- #35
- #34
- #33
- #32
- #31
- #30
- #29
- #28
- #27
- #26
- #25
- #24
- #23
- #22
- #21
- #20
- #19
- #18
- #17
- #16
- #15
- #14
- #13
- #12
- #11
- #10
- #9
- #8
- #7
- #6
- #5
- #4
- #3
- #2
- #1