├── .gitignore
├── LICENSE
├── README.md
├── django_translation
├── Dockerfile
├── django_translation
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── locale
│ └── zh_Hant
│ │ └── LC_MESSAGES
│ │ ├── django.po
│ │ └── djangojs.po
├── manage.py
├── requirements.txt
└── tutorial
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ └── __init__.py
│ ├── models.py
│ ├── static
│ └── js
│ │ └── index.js
│ ├── templates
│ └── tutorial
│ │ └── index.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
└── docker-compose.yml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # django-translation-tutorial
2 |
3 | 如何使用 Django 實作 translation 📝
4 |
5 | * [Youtube Tutorial PART 1 - django-translation-tutorial](https://youtu.be/9zFCfnVgXjs)
6 |
7 | * [Youtube Tutorial PART 2 - django-translation-tutorial](https://youtu.be/sz0cpt8I1fM)
8 |
9 | * [Youtube Tutorial PART 3 - django-translation-tutorial](https://youtu.be/9njecageJvM)
10 |
11 | ## 簡介
12 |
13 | 本篇文章將介紹如何使用 Django 實作 translation ,我參考了 Django 官網的 [translation 文件](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/),
14 |
15 | 並且紀錄了一些細節。如果你想用 Flask 實作的話,可參考我之前寫的文章 [Flask-Babel-example](https://github.com/twtrubiks/Flask-Babel-example)。
16 |
17 | 建議閱讀此篇文章之前,要對 docker 有一些基本的認識,如果你對 docker 不熟,建議可參考
18 |
19 | [Docker 基本教學 - 從無到有 Docker-Beginners-Guide](https://github.com/twtrubiks/docker-tutorial),為什麼會使用到 docker :question:
20 |
21 | 因為本身電腦是 windows,而 Django translation 需要安裝 `gettext`,我在 windows 中一直裝不起來,
22 |
23 | 所以最後果斷使用 docker :sweat_smile:
24 |
25 | ## 建立環境
26 |
27 | 我使用 docker 建立環境,先來看一下 [Dockerfile](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/Dockerfile),
28 |
29 | ```text
30 | FROM python:3.6.2
31 | LABEL maintainer twtrubiks
32 | ENV PYTHONUNBUFFERED 1
33 | RUN mkdir /docker_tutorial
34 | WORKDIR /docker_tutorial
35 | COPY . /docker_tutorial/
36 | RUN pip install -r requirements.txt
37 | RUN apt-get update && \
38 | apt-get install -y gettext && \
39 | apt-get clean && rm -rf /var/cache/apt/* && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/*
40 | ```
41 |
42 | 最重要的就是 `apt-get install -y gettext` 這個,我會用 docker 也是因為這個原因,windows 一直裝不起來阿:cry:
43 |
44 | 如果你是 Linux 或是 MAC,應該就不需要用 docker 了,本機理論上很好安裝。
45 |
46 | 接著執行以下指令建立環境,
47 |
48 | ```cmd
49 | docker-compose build
50 | ```
51 |
52 | 再啟動環境 ( 其實也可以直接執行這個就好 ),
53 |
54 | ```cmd
55 | docker-compose up
56 | ```
57 |
58 | 再來進入 docker 環境中 migrate,
59 |
60 | ```python
61 | python manage.py migrate
62 | ```
63 |
64 | 如果上述不了解,可參考 [Docker 基本教學 - 從無到有 Docker-Beginners-Guide](https://github.com/twtrubiks/docker-tutorial)。
65 |
66 | 來看一下 [requirements.txt](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/requirements.txt),這裡使用的是 `django==2.1.1`。
67 |
68 | 之前我寫的 django 教學文章,可參考 [Django 基本教學 - 從無到有 Django-Beginners-Guide 📝](https://github.com/twtrubiks/django-tutorial),不過要注意的是,
69 |
70 | 這篇教學是 `django <= 2.0`,django 2 有機會我會再寫篇文章介紹。
71 |
72 | 由於 django 2 改動蠻大的,所以我在程式碼中,有些地方會增加註解,說明這段設定可以參考官網的哪部分文件。
73 |
74 | ## 教學
75 |
76 | 接下來就要教大家如何進行翻譯了,首先,先進入 [django_translation/settings.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/django_translation/settings.py),
77 |
78 | 找到 MIDDLEWARE,並且加入 `django.middleware.locale.LocaleMiddleware`,這邊要注意擺放的位置,
79 |
80 | ```python
81 | MIDDLEWARE = [
82 | ...
83 | 'django.contrib.sessions.middleware.SessionMiddleware',
84 |
85 | # https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#how-django-discovers-language-preference
86 | 'django.middleware.locale.LocaleMiddleware',
87 |
88 | 'django.middleware.common.CommonMiddleware',
89 | ...
90 | ]
91 | ```
92 |
93 | 一定要放在 `django.contrib.sessions.middleware.SessionMiddleware` 之後,
94 |
95 | 以及 `django.middleware.common.CommonMiddleware` 之前,原因如下,
96 |
97 | 下方為官方說明,
98 |
99 | ```text
100 | It should come after SessionMiddleware, because LocaleMiddleware makes use of session
101 | data. And it should come before CommonMiddleware because CommonMiddleware needs an
102 | activated language in order to resolve the requested URL.
103 | ```
104 |
105 | 詳細的官方文件,可參考 [How Django discovers language preference](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#how-django-discovers-language-preference)。
106 |
107 | 設定 LOCALE_PATHS, 可參考 [setting-LOCALE_PATHS](https://docs.djangoproject.com/en/2.1/ref/settings/#std:setting-LOCALE_PATHS),
108 |
109 | 在 [django_translation/settings.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/django_translation/settings.py) 中增加以下 code,這資料夾到時候會擺放翻譯的 `django.po` 以及 `django.mo` 檔案。
110 |
111 | ```python
112 | LOCALE_PATHS = [
113 | os.path.join(BASE_DIR, 'locale'),
114 | ]
115 | ```
116 |
117 | 在 [django_translation/settings.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/django_translation/settings.py) 中的 LANGUAGE_CODE 為預設的語言
118 |
119 | ```python
120 | LANGUAGE_CODE = 'en-us'
121 | ```
122 |
123 | 如果你不知道國家的 LANGUAGE_CODE,可到 [language-identifiers.html](http://www.i18nguy.com/unicode/language-identifiers.html) 查詢各國家的 LANGUAGE_CODE
124 | 。
125 |
126 | 接著在 [django_translation/settings.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/django_translation/settings.py) 中設定可以顯示的語言清單,增加下列 code,
127 |
128 | ```python
129 | from django.utils.translation import gettext_lazy as _
130 | LANGUAGES = [
131 | ('en-us', _('English')),
132 | ('zh-hant', _('Traditional Chinese')),
133 | ('zh-cn', _('Simplified Chinese')),
134 | ]
135 | ```
136 |
137 | `from django.utils.translation import gettext_lazy as _` 為翻譯,可參考 [standard-translation](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#standard-translation) ,
138 |
139 | 然後非常建議大家在看一下 [lazy-translation](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#lazy-translation) 這篇,了解哪時候要使用 `gettext_lazy` 以及為什麼要使用
140 |
141 | `gettext_lazy`,通常是 defining models, forms and model forms 這些地方。
142 |
143 | 更多詳細設定,可參考
144 | [How Django discovers language preference](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#how-django-discovers-language-preference)。
145 |
146 | [django_translation/settings.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/django_translation/settings.py) 的設定到這邊就算告一個段落了:relaxed:
147 |
148 | 接著設定 [django_translation/urls.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/django_translation/urls.py) ,我們要增加 `path('i18n/', include('django.conf.urls.i18n'))`
149 |
150 | 到 urlpatterns 中,這個主要目的是 Activate this view,
151 |
152 | 以下為官方文件說明
153 |
154 | ```text
155 | As a convenience, Django comes with a view, django.views.i18n.set_language(), that sets
156 | a user’s language preference and redirects to a given URL or, by default, back to the
157 | previous page.
158 | Activate this view by adding the following line to your URLconf:
159 | ```
160 |
161 | 詳細可參考 [the-set-language-redirect-view](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#the-set-language-redirect-view)。
162 |
163 | ```python
164 | urlpatterns = [
165 | # https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#the-set-language-redirect-view
166 | path('i18n/', include('django.conf.urls.i18n')),
167 | path('admin/', admin.site.urls),
168 | path('tutorial/', include('tutorial.urls', namespace='tutorial' )),
169 | ]
170 | ```
171 |
172 | 接著設定 [tutorial/urls.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/urls.py),設定好了之後,來看 [tutorial/views.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/views.py),
173 |
174 | 讓我們來看在 view 中要怎麼實現翻譯, code 如下,
175 |
176 | ```python
177 | from django.shortcuts import render
178 | from django.utils.translation import gettext as _
179 |
180 | # Create your views here.
181 | def index(request):
182 | data = _('Hello')
183 |
184 | return render(request, 'tutorial/index.html', {
185 | "data" : data
186 | })
187 | ```
188 |
189 | `_('Hello')` 這個就是翻譯。
190 |
191 | ( 像這邊就是使用 `from django.utils.translation import gettext as _`,而不是 `gettext_lazy`。)
192 |
193 | 有 view 之後,那接下來就是設定 [tutorial/templates/tutorial/index.html](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/templates/tutorial/index.html)。
194 |
195 | 首先,我們先來設定可以切換語言的 select,可參考 [the-set-language-redirect-view](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#the-set-language-redirect-view),
196 |
197 | 以下為官方範例 code,
198 |
199 | ```django
200 | {% load i18n %}
201 |
202 |
216 | ```
217 |
218 | `{% load i18n %}` 很重要 ( 可參考 [internationalization-in-template-code](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#internationalization-in-template-code) 這邊的說明 ),記得要載入,
219 |
220 | 我自己有簡單的使用 bootstrap3,可參考 [tutorial/templates/tutorial/index.html](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/templates/tutorial/index.html),直接將翻譯文字顯示出來,
221 |
222 | 如下方 code,
223 |
224 | ```html
225 | {{data}}
226 | ```
227 |
228 | 到這邊,我們終於可以開始進行翻譯了:satisfied: ( 這邊我就只翻譯繁體,其他的以此類推 )。
229 |
230 | 首先需要先執行 [makemessages](https://docs.djangoproject.com/en/2.1/ref/django-admin/#makemessages) 指令,建立出 `django.po` 檔案,指令如下,
231 |
232 | ```cmd
233 | django-admin makemessages --locale=zh_Hant
234 | ```
235 |
236 | 這段 code ,會去 scan 你的 code ,將需要翻譯的找出來。 ( 例如 `_('Hello')` 就會被 scan 出來 )。
237 |
238 | 
239 |
240 | 注意,如果出現如下圖錯誤,
241 |
242 | 
243 |
244 | ```text
245 | CommandError: Can't find msguniq. Make sure you have GNU gettext tools 0.15 or newer installed.
246 | ```
247 |
248 | 這就是在 windows 上為什麼我用 docker 的原因,雖然網路上有人說 windows 可安裝 [gettext-iconv-windows](https://mlocati.github.io/articles/gettext-iconv-windows.html) 解決,
249 |
250 | 但我一直遇到問題,最後果斷使用 docker:smiley:
251 |
252 | 目錄中應該會有個 locale 的資料夾,因為我們在 LOCALE_PATHS 有設定,如果沒有請自行建立一個
253 |
254 | ( 當 django run 起來的時候應該就會自己建立了 )。
255 |
256 | 執行後會看到如下,產生了 zh_Hant 的 `django.po` 檔案,
257 |
258 | 
259 |
260 | 現在就是要對 `django.po` 進行翻譯,打開 `django.po`,你會發現 `'Hello'` 在裡面,
261 |
262 | 
263 |
264 | 將它翻譯後,再執行 compilemessages,可參考 [compilemessages](https://docs.djangoproject.com/en/2.1/ref/django-admin/#compilemessages),指令如下
265 |
266 | ```python
267 | django-admin compilemessages
268 | ```
269 |
270 | 
271 |
272 | 執行後,如果沒任何錯誤訊息,就是成功 compilemessages,`django.mo` 就是 compilemessages 過後的檔案。
273 |
274 | 
275 |
276 | 接著我們到網頁上觀看 [http://127.0.0.1:8000/tutorial/](http://127.0.0.1:8000/tutorial/),
277 |
278 | 英文
279 |
280 | 
281 |
282 | 中文
283 |
284 | 
285 |
286 | 我們也可以這樣寫,
287 |
288 | ```python
289 | m=1
290 | d= 20
291 | output = _('Today is %(month)s / %(day)s.') % {'month': m, 'day': d}
292 | ```
293 |
294 | [django.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/django.po) 如下,
295 |
296 | 
297 |
298 | 這邊要提醒大家,假如你有做任何修改時,重新執行了 `django-admin makemessages --locale=zh_Hant` 時,
299 |
300 | 你可能會看到像上圖 A 的部份,就是你修改之前的東西會幫你註解起來,我建議把這個都刪除,也就是 A 的部份。
301 |
302 | ( 會請大家刪除的原因是,有時候它會導致你翻譯翻不出來,最後我是把那部份都刪除後,再執行 compilemessages 就正常了 )
303 |
304 | 
305 |
306 | ### contextual-markers
307 |
308 | 什麼時候會用到它呢 ? 在英文翻中文常常會有這種況狀,就是一個英文的詞,在中文有很多意思的時候。
309 |
310 | 舉個例子, blue 是 藍色 的意思,但 blue 也可以是 鬱悶 的意思,這時候,就需要使用 contextual-markers,
311 |
312 | 參考以下 code ( 更多說明請參考 [contextual-markers](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#contextual-markers) ),code 在 [tutorial/views.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/views.py),
313 |
314 | ```python
315 | ...
316 | from django.utils.translation import pgettext
317 |
318 | # Create your views here.
319 | def index(request):
320 | ...
321 | # Translators: contextual-markers
322 | p_blue_color = pgettext("color", "blue")
323 | # Translators: contextual-markers
324 | p_blue_mood = pgettext("mood", "blue")
325 | ...
326 | return render(request, 'tutorial/index.html', {
327 | ...
328 | "p_blue_color": p_blue_color,
329 | "p_blue_mood": p_blue_mood,
330 | ....
331 | })
332 | ```
333 |
334 | 然後如果們執行 `django-admin makemessages --locale=zh_Hant`,你會發現 [django.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/django.po) 如下,
335 |
336 | 
337 |
338 | 你會發現它被拆成兩個,將對應要翻譯的內容填進去就可以了。另外注意一下這個註解,也就是
339 |
340 | `# Translators: contextual-markers` 這個,如果你要在翻譯中註解,你可以在 python 中使用
341 |
342 | `# Translators` key 開頭,這樣 [django.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/django.po) 就會有註解,更多詳細介紹可參考 [comments-for-translators](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#comments-for-translators)。
343 |
344 | 翻譯完成後,再執行 compilemessages,
345 |
346 | 如果是在 html 中想要使用 contextual-markers,則必須使用以下 code,
347 |
348 | ```django
349 | {# contextual-markers #}
350 | {% trans "blue" context "color" %}
351 | {% trans "blue" context "mood" %}
352 | ```
353 |
354 | 
355 |
356 | ### pluralization
357 |
358 | 有時候我們會有單數和複數顯示不同的需求,這時候就可以使用
359 | [pluralization](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#pluralization),官方說明如下
360 |
361 | ```text
362 | ngettext() takes three arguments: the singular translation string, the plural translation
363 | string and the number of objects.
364 | ```
365 |
366 | 範例 code,code 在 [tutorial/views.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/views.py),
367 |
368 | ```python
369 | from django.utils.translation import ngettext
370 | # pluralization
371 | count = 2
372 | pluralization = ngettext(
373 | 'There is %(count)d %(name)s object available.',
374 | 'There are %(count)d %(name)s objects available.',
375 | count
376 | ) % {
377 | 'count': count,
378 | 'name':'test',
379 | }
380 | ```
381 |
382 | 執行 makemessages,
383 |
384 | 
385 |
386 | 在 html 中,
387 |
388 | ```html
389 | {# pluralization #}
390 | {{pluralization}}
391 | ```
392 |
393 | 
394 |
395 | 你可以把 count 改成 `count = 1`,這樣就會變成單數了。
396 |
397 | ### Internationalization: in template code
398 |
399 | 接著來看在 template 中要如何進行翻譯,請參考 [tutorial/templates/tutorial/index.html](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/templates/tutorial/index.html),
400 |
401 | ```django
402 | {% load i18n %}
403 |
404 | {% comment %}Translators: Hello Django{% endcomment %}
405 | {% trans "Hello Django" %}
406 |
407 | {# Translators: comment #}
408 | {% trans "comment" %}
409 | ```
410 |
411 | 上面提供了兩種的註解方式,詳細可參考 [comments-for-translators-in-templates](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#comments-for-translators-in-templates)。
412 |
413 | `{% load i18n %}` 記得要載入,
414 |
415 | 接著執行 `django-admin makemessages --locale=zh_Hant` 產生 [django.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/django.po) 檔案
416 |
417 | 
418 |
419 | 註解也會產生在你的 [django.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/django.po) 中,最後 compilemessages,
420 |
421 | 
422 |
423 | 另外還有一種是設定為變數,方法如下
424 |
425 | ```django
426 | {# Translators: var #}
427 | {% trans "This is the title" as the_title %}
428 | {{ the_title }}
429 | ```
430 |
431 | 剩下的部分和剛剛都一樣,這邊我就不再做一遍了。
432 |
433 | 接下來是可能有一種情況,例如,英文是顯示 `show Hello`,而中文要顯示 `哈摟顯示`,
434 |
435 | 這時候,我們就不能使用之前的 `{% trans "This is the title" %}` 的方法,因為中英的位置
436 |
437 | 不一樣,這時候,就必須使用 `Translators: "{% blocktrans %}....{% endblocktrans %}` 的方式,
438 |
439 | 下列為變數的方法,寫法有兩種,code 請參考 [tutorial/templates/tutorial/index.html](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/templates/tutorial/index.html),
440 |
441 | ```django
442 | {# Translators: "{% blocktrans %}....{% endblocktrans %} #}
443 | {%blocktrans with d=data %}show {{d}}{%endblocktrans%}
444 | {%blocktrans with data as d %}show {{d}}{%endblocktrans%}
445 | ```
446 |
447 | 接著執行 `django-admin makemessages --locale=zh_Hant` 產生 [django.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/django.po) 檔案,
448 |
449 | 
450 |
451 | 剩下的步驟這邊就省略了:relaxed:前面都說很多次了。
452 |
453 | 再來說一下 `trimmed option`,
454 |
455 | 有時候,我們希望經過 `django-admin makemessages --locale=zh_Hant` 產生 [django.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/django.po) 的檔案不要有換行
456 |
457 | 字元 `\n` 這類的,這時候,就可以使用 trimmed 這個 option。
458 |
459 | ( 有時候 `\n` 這類的字元甚至會導致翻譯錯誤,所以建議能加 trimmed 就加吧 )
460 |
461 | ```django
462 | {% blocktrans trimmed %}
463 | First sentence.
464 | Second sentence.
465 | {% endblocktrans %}
466 | ```
467 |
468 | 再來說一下另一個 `noop option`,官方說明如下,
469 |
470 | ```text
471 | If the noop option is present, variable lookup still takes place but the translation is
472 | skipped. This is useful when “stubbing out” content that will require translation in
473 | the future:
474 | ```
475 |
476 | 如果加上這個 `noop option`,它將不會被翻譯,經過 `django-admin makemessages --locale=zh_Hant`
477 |
478 | 產生 [django.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/django.po) 的檔案中,還是會有翻譯的內容,但不會被翻譯出來( skipped ),也就是說,可以使用在未來
479 |
480 | 會翻譯,但目前還不需要的情境下,
481 |
482 | ```django
483 | {# Translators: noop #}
484 | {% trans "myvar" noop %}
485 | ```
486 |
487 | ### Internationalization: in JavaScript code
488 |
489 | * [Youtube Tutorial PART 3 - django-translation-tutorial](https://youtu.be/9njecageJvM)
490 |
491 | 一定會有人問,那如果我是透過 javascript ,有辦法進行翻譯嗎:question:
492 |
493 | 是可以的:satisfied:這邊就來教大家如何設定,
494 |
495 | 先到 [django_translation/urls.py](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/django_translation/urls.py) 設定 [The JavaScriptCatalog view](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#module-django.views.i18n),
496 |
497 | ```python
498 | from django.views.i18n import JavaScriptCatalog
499 |
500 | urlpatterns = [
501 | ....
502 | #https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#module-django.views.i18n
503 | path('jsi18n/', JavaScriptCatalog.as_view(), name='javascript-catalog'),
504 | ...
505 | ]
506 | ```
507 |
508 | 接著在 [tutorial/templates/tutorial/index.html](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/templates/tutorial/index.html) 中新增以下 code,
509 |
510 | ```django
511 | {# Using the JavaScript translation catalog #}
512 | {# https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#using-the-javascript-translation-catalog #}
513 |
514 | ```
515 |
516 | 更多詳細介紹可參考官方文件 [using-the-javascript-translation-catalog](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#using-the-javascript-translation-catalog)。
517 |
518 | 接下來請注意,請 **新增一個 js 檔案** ,不能直接將 js 寫在 [tutorial/templates/tutorial/index.html](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/templates/tutorial/index.html) 中,
519 |
520 | 會抓不到,所以我們新增一個 [tutorial/static/js/index.js](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/static/js/index.js) 檔案,並且在裡面填入以下 code,
521 |
522 | 使用方法也很簡單,和在 python 翻譯的時候差不多,考以直接使用 [gettext](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#gettext),
523 |
524 | ```javascript
525 | var data = gettext('this is to be translated')
526 | document.write( ''+ data + '
');
527 | ```
528 |
529 | 之後再回到 [tutorial/templates/tutorial/index.html](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/tutorial/templates/tutorial/index.html) 中 import 它,
530 |
531 | ```django
532 | {% load static %}
533 |
534 | ```
535 |
536 | 接著我們要建立 [djangojs.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/djangojs.po),指令有點不一樣,
537 |
538 | ```python
539 | django-admin makemessages -d djangojs -l zh_Hant
540 | ```
541 |
542 | 
543 |
544 | 執行後你會發現多出 [djangojs.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/djangojs.po),
545 |
546 | 
547 |
548 | [djangojs.po](https://github.com/twtrubiks/django-translation-tutorial/blob/master/django_translation/locale/zh_Hant/LC_MESSAGES/djangojs.po) 的內容如下,這邊我們成功的抓到 js 裡面的翻譯,
549 |
550 | 
551 |
552 | 更多詳細可參考 [Creating message files from JavaScript source code](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#creating-message-files-from-javascript-source-code),
553 |
554 | 接著執行 compilemessages,指令則是一樣的,`django-admin compilemessages`
555 |
556 | 
557 |
558 | 最後再到網頁上觀看 [http://127.0.0.1:8000/tutorial/](http://127.0.0.1:8000/tutorial/),js 也成功翻譯了:smiley:
559 |
560 | 
561 |
562 | ## 後記:
563 |
564 | 這次一不小心寫了好多,很多地方基本上我都有在 code 的部分放上註解以及官方的參考網址,
565 |
566 | 整體來說,我覺得 [django-translation](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/) 蠻完善的,連 js 也整合了進來,這次就介紹到這邊,謝謝大家:heart_eyes:
567 |
568 | ## 執行環境
569 |
570 | * Python 3.6.2
571 | * windows 10
572 |
573 | ## Reference
574 |
575 | * [django-translation](https://docs.djangoproject.com/en/2.1/topics/i18n/translation/)
576 |
577 | * [django-bootstrap3](https://github.com/dyve/django-bootstrap3)
578 |
579 | ## Donation
580 |
581 | 文章都是我自己研究內化後原創,如果有幫助到您,也想鼓勵我的話,歡迎請我喝一杯咖啡:laughing:
582 |
583 | 
584 |
585 | [贊助者付款](https://payment.opay.tw/Broadcaster/Donate/9E47FDEF85ABE383A0F5FC6A218606F8)
586 |
587 | ## License
588 |
589 | MIT license
590 |
--------------------------------------------------------------------------------
/django_translation/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.6.2
2 | LABEL maintainer twtrubiks
3 | ENV PYTHONUNBUFFERED 1
4 | RUN mkdir /docker_tutorial
5 | WORKDIR /docker_tutorial
6 | COPY . /docker_tutorial/
7 | RUN pip install -r requirements.txt
8 | RUN apt-get update && \
9 | apt-get install -y gettext && \
10 | apt-get clean && rm -rf /var/cache/apt/* && rm -rf /var/lib/apt/lists/* && rm -rf /tmp/*
11 |
12 |
--------------------------------------------------------------------------------
/django_translation/django_translation/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twtrubiks/django-translation-tutorial/e76cbb0bf9f4c18b2f4159888a3e30d63bf8f34f/django_translation/django_translation/__init__.py
--------------------------------------------------------------------------------
/django_translation/django_translation/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for django_translation project.
3 |
4 | Generated by 'django-admin startproject' using Django 2.1.1.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.1/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/2.1/ref/settings/
11 | """
12 |
13 | import os
14 | from django.utils.translation import gettext_lazy as _
15 |
16 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
17 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
18 |
19 |
20 | # Quick-start development settings - unsuitable for production
21 | # See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
22 |
23 | # SECURITY WARNING: keep the secret key used in production secret!
24 | SECRET_KEY = 'vf9ar&^ulzdg6*)vj5i=!k26^#=*v3)i3!(=41r9)*@!m5lgvd'
25 |
26 | # SECURITY WARNING: don't run with debug turned on in production!
27 | DEBUG = True
28 |
29 | ALLOWED_HOSTS = []
30 |
31 |
32 | # Application definition
33 |
34 | INSTALLED_APPS = [
35 | 'django.contrib.admin',
36 | 'django.contrib.auth',
37 | 'django.contrib.contenttypes',
38 | 'django.contrib.sessions',
39 | 'django.contrib.messages',
40 | 'django.contrib.staticfiles',
41 | 'bootstrap3',
42 | 'tutorial',
43 | ]
44 |
45 | MIDDLEWARE = [
46 | 'django.middleware.security.SecurityMiddleware',
47 | 'django.contrib.sessions.middleware.SessionMiddleware',
48 |
49 | # https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#how-django-discovers-language-preference
50 | 'django.middleware.locale.LocaleMiddleware',
51 |
52 | 'django.middleware.common.CommonMiddleware',
53 | 'django.middleware.csrf.CsrfViewMiddleware',
54 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
55 | 'django.contrib.messages.middleware.MessageMiddleware',
56 | 'django.middleware.clickjacking.XFrameOptionsMiddleware',
57 | ]
58 |
59 | ROOT_URLCONF = 'django_translation.urls'
60 |
61 | TEMPLATES = [
62 | {
63 | 'BACKEND': 'django.template.backends.django.DjangoTemplates',
64 |
65 | # https://docs.djangoproject.com/en/2.1/howto/overriding-templates/#overriding-from-the-project-s-templates-directory
66 | 'DIRS': [os.path.join(BASE_DIR, 'templates')],
67 |
68 | 'APP_DIRS': True,
69 | 'OPTIONS': {
70 | 'context_processors': [
71 | 'django.template.context_processors.debug',
72 | 'django.template.context_processors.request',
73 | 'django.contrib.auth.context_processors.auth',
74 | 'django.contrib.messages.context_processors.messages',
75 | ],
76 | },
77 | },
78 | ]
79 |
80 | WSGI_APPLICATION = 'django_translation.wsgi.application'
81 |
82 |
83 | # Database
84 | # https://docs.djangoproject.com/en/2.1/ref/settings/#databases
85 |
86 | DATABASES = {
87 | 'default': {
88 | 'ENGINE': 'django.db.backends.sqlite3',
89 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
90 | }
91 | }
92 |
93 |
94 | # Password validation
95 | # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
96 |
97 | AUTH_PASSWORD_VALIDATORS = [
98 | {
99 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
100 | },
101 | {
102 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
103 | },
104 | {
105 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
106 | },
107 | {
108 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
109 | },
110 | ]
111 |
112 |
113 | # Internationalization
114 | # https://docs.djangoproject.com/en/2.1/topics/i18n/
115 |
116 | # https://docs.djangoproject.com/en/2.1/ref/settings/#std:setting-LOCALE_PATHS
117 | LOCALE_PATHS = [
118 | os.path.join(BASE_DIR, 'locale'),
119 | ]
120 |
121 | # https://docs.djangoproject.com/en/2.1/ref/settings/#std:setting-LANGUAGE_CODE
122 | LANGUAGE_CODE = 'en-us'
123 |
124 | # https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#how-django-discovers-language-preference
125 | # http://www.i18nguy.com/unicode/language-identifiers.html
126 | LANGUAGES = [
127 | ('en-us', _('English')),
128 | ('zh-hant', _('Traditional Chinese')),
129 | ('zh-cn', _('Simplified Chinese')),
130 | ]
131 |
132 | TIME_ZONE = 'UTC'
133 |
134 | USE_I18N = True
135 |
136 | USE_L10N = True
137 |
138 | USE_TZ = True
139 |
140 |
141 | # Static files (CSS, JavaScript, Images)
142 | # https://docs.djangoproject.com/en/2.1/howto/static-files/
143 |
144 | STATIC_URL = '/static/'
145 |
--------------------------------------------------------------------------------
/django_translation/django_translation/urls.py:
--------------------------------------------------------------------------------
1 | """django_translation URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/2.1/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path,include
18 | from django.views.i18n import JavaScriptCatalog
19 |
20 | urlpatterns = [
21 | # https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#the-set-language-redirect-view
22 | path('i18n/', include('django.conf.urls.i18n')),
23 | #https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#module-django.views.i18n
24 | path('jsi18n/', JavaScriptCatalog.as_view(), name='javascript-catalog'),
25 | path('admin/', admin.site.urls),
26 | path('tutorial/', include('tutorial.urls', namespace='tutorial' )),
27 | ]
28 |
29 |
--------------------------------------------------------------------------------
/django_translation/django_translation/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for django_translation project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_translation.settings')
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/django_translation/locale/zh_Hant/LC_MESSAGES/django.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 | # This file is distributed under the same license as the PACKAGE package.
4 | # FIRST AUTHOR , YEAR.
5 | #
6 | #, fuzzy
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: PACKAGE VERSION\n"
10 | "Report-Msgid-Bugs-To: \n"
11 | "POT-Creation-Date: 2018-09-05 10:17+0000\n"
12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 | "Last-Translator: FULL NAME \n"
14 | "Language-Team: LANGUAGE \n"
15 | "Language: \n"
16 | "MIME-Version: 1.0\n"
17 | "Content-Type: text/plain; charset=UTF-8\n"
18 | "Content-Transfer-Encoding: 8bit\n"
19 | "Plural-Forms: nplurals=1; plural=0;\n"
20 |
21 | #: django_translation/settings.py:127
22 | msgid "English"
23 | msgstr ""
24 |
25 | #: django_translation/settings.py:128
26 | msgid "Traditional Chinese"
27 | msgstr ""
28 |
29 | #: django_translation/settings.py:129
30 | msgid "Simplified Chinese"
31 | msgstr ""
32 |
33 | #. Translators: contextual-markers
34 | #: tutorial/templates/tutorial/index.html:54 tutorial/views.py:15
35 | msgctxt "color"
36 | msgid "blue"
37 | msgstr "藍色"
38 |
39 | #. Translators: contextual-markers
40 | #: tutorial/templates/tutorial/index.html:55 tutorial/views.py:17
41 | msgctxt "mood"
42 | msgid "blue"
43 | msgstr "鬱悶"
44 |
45 | #. Translators: Hello Django
46 | #: tutorial/templates/tutorial/index.html:61
47 | msgid "Hello Django"
48 | msgstr "哈摟 Django"
49 |
50 | #. Translators: comment
51 | #: tutorial/templates/tutorial/index.html:64
52 | msgid "comment"
53 | msgstr "註解"
54 |
55 | #. Translators: var
56 | #: tutorial/templates/tutorial/index.html:67
57 | msgid "This is the title"
58 | msgstr "這是標題"
59 |
60 | #. Translators: "{% blocktrans %}....{% endblocktrans %}
61 | #: tutorial/templates/tutorial/index.html:71
62 | #: tutorial/templates/tutorial/index.html:72
63 | #, python-format
64 | msgid "show %(d)s"
65 | msgstr "%(d)s 顯示"
66 |
67 | #: tutorial/templates/tutorial/index.html:76
68 | msgid "First sentence. Second sentence."
69 | msgstr "第一. 第二"
70 |
71 | #. Translators: noop
72 | #: tutorial/templates/tutorial/index.html:83
73 | msgid "myvar"
74 | msgstr "我的 var"
75 |
76 | #: tutorial/views.py:8
77 | msgid "Hello"
78 | msgstr "哈摟"
79 |
80 | #: tutorial/views.py:12
81 | #, python-format
82 | msgid "Today is %(month)s / %(day)s."
83 | msgstr "今天是 %(month)s 月 %(day)s 日"
84 |
85 | #: tutorial/views.py:22
86 | #, python-format
87 | msgid "There is %(count)d %(name)s object available."
88 | msgid_plural "There are %(count)d %(name)s objects available."
89 | msgstr[0] "有 %(count)d 個 %(name)s 物件可用"
90 |
--------------------------------------------------------------------------------
/django_translation/locale/zh_Hant/LC_MESSAGES/djangojs.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 | # This file is distributed under the same license as the PACKAGE package.
4 | # FIRST AUTHOR , YEAR.
5 | #
6 | #, fuzzy
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: PACKAGE VERSION\n"
10 | "Report-Msgid-Bugs-To: \n"
11 | "POT-Creation-Date: 2018-09-04 14:01+0000\n"
12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 | "Last-Translator: FULL NAME \n"
14 | "Language-Team: LANGUAGE \n"
15 | "Language: \n"
16 | "MIME-Version: 1.0\n"
17 | "Content-Type: text/plain; charset=UTF-8\n"
18 | "Content-Transfer-Encoding: 8bit\n"
19 | "Plural-Forms: nplurals=1; plural=0;\n"
20 |
21 | #: tutorial/static/index.js:1
22 | msgid "this is to be translated"
23 | msgstr "我將被翻譯"
24 |
--------------------------------------------------------------------------------
/django_translation/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == '__main__':
6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_translation.settings')
7 | try:
8 | from django.core.management import execute_from_command_line
9 | except ImportError as exc:
10 | raise ImportError(
11 | "Couldn't import Django. Are you sure it's installed and "
12 | "available on your PYTHONPATH environment variable? Did you "
13 | "forget to activate a virtual environment?"
14 | ) from exc
15 | execute_from_command_line(sys.argv)
16 |
--------------------------------------------------------------------------------
/django_translation/requirements.txt:
--------------------------------------------------------------------------------
1 | django==2.1.1
2 | django-bootstrap3==11.0.0
3 |
--------------------------------------------------------------------------------
/django_translation/tutorial/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twtrubiks/django-translation-tutorial/e76cbb0bf9f4c18b2f4159888a3e30d63bf8f34f/django_translation/tutorial/__init__.py
--------------------------------------------------------------------------------
/django_translation/tutorial/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/django_translation/tutorial/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class TutorialConfig(AppConfig):
5 | name = 'tutorial'
6 |
--------------------------------------------------------------------------------
/django_translation/tutorial/migrations/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/twtrubiks/django-translation-tutorial/e76cbb0bf9f4c18b2f4159888a3e30d63bf8f34f/django_translation/tutorial/migrations/__init__.py
--------------------------------------------------------------------------------
/django_translation/tutorial/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/django_translation/tutorial/static/js/index.js:
--------------------------------------------------------------------------------
1 | var data = gettext('this is to be translated')
2 | document.write( ''+ data + '
');
3 |
--------------------------------------------------------------------------------
/django_translation/tutorial/templates/tutorial/index.html:
--------------------------------------------------------------------------------
1 | {% load i18n bootstrap3 %}
2 |
3 |
4 |
5 |
6 |
7 | Tutorial
8 |
12 | {# Load CSS and JavaScript #}
13 | {% bootstrap_css %}
14 | {% bootstrap_javascript %}
15 | {% load static %}
16 |
17 |
18 |
19 |
20 |
django-translation-tutorial
21 |
22 | {% get_current_language as LANGUAGE_CODE %}
23 |
LANGUAGE : {{LANGUAGE_CODE}}
24 |
25 |
49 |
50 |
{{data}}
51 |
{{output}}
52 |
53 | {# contextual-markers #}
54 |
{% trans "blue" context "color" %}
55 |
{% trans "blue" context "mood" %}
56 |
57 | {# pluralization #}
58 |
{{pluralization}}
59 |
60 | {% comment %}Translators: Hello Django{% endcomment %}
61 |
{% trans "Hello Django" %}
62 |
63 | {# Translators: comment #}
64 |
{% trans "comment" %}
65 |
66 | {# Translators: var #}
67 | {% trans "This is the title" as the_title %}
68 |
{{ the_title }}
69 |
70 | {# Translators: "{% blocktrans %}....{% endblocktrans %} #}
71 |
{%blocktrans with d=data %}show {{d}}{%endblocktrans%}
72 |
{%blocktrans with data as d %}show {{d}}{%endblocktrans%}
73 |
74 | {# Translators: trimmed option #}
75 |
76 | {% blocktrans trimmed %}
77 | First sentence.
78 | Second sentence.
79 | {% endblocktrans %}
80 |
81 |
82 | {# Translators: noop #}
83 |
{% trans "myvar" noop %}
84 |
85 | {# Using the JavaScript translation catalog #}
86 | {# https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#using-the-javascript-translation-catalog #}
87 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/django_translation/tutorial/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/django_translation/tutorial/urls.py:
--------------------------------------------------------------------------------
1 | from django.urls import path
2 | from . import views
3 |
4 | app_name = 'index'
5 | urlpatterns = [
6 | path('', views.index,name='index'),
7 | ]
8 |
--------------------------------------------------------------------------------
/django_translation/tutorial/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 | from django.utils.translation import gettext as _
3 | from django.utils.translation import pgettext
4 | from django.utils.translation import ngettext
5 |
6 | # Create your views here.
7 | def index(request):
8 | data = _('Hello')
9 |
10 | m=1
11 | d= 20
12 | output = _('Today is %(month)s / %(day)s.') % {'month': m, 'day': d}
13 |
14 | # Translators: contextual-markers
15 | p_blue_color = pgettext("color", "blue")
16 | # Translators: contextual-markers
17 | p_blue_mood = pgettext("mood", "blue")
18 |
19 | # pluralization
20 | count = 2
21 | pluralization = ngettext(
22 | 'There is %(count)d %(name)s object available.',
23 | 'There are %(count)d %(name)s objects available.',
24 | count
25 | ) % {
26 | 'count': count,
27 | 'name':'test',
28 | }
29 |
30 | return render(request, 'tutorial/index.html', {
31 | "data" : data,
32 | "output" : output,
33 | "p_blue_color": p_blue_color,
34 | "p_blue_mood": p_blue_mood,
35 | "pluralization" : pluralization
36 | })
37 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 |
4 | web:
5 | build: ./django_translation
6 | command: python manage.py runserver 0.0.0.0:8000
7 | restart: always
8 | volumes:
9 | - ./django_translation:/docker_tutorial
10 | # (HOST:CONTAINER)
11 | ports:
12 | - "8000:8000"
13 |
--------------------------------------------------------------------------------