Django was originally developed smack in the middle of the United States (literally; Lawrence, Kansas, is less than 40 miles from the geographic center of the continental United States). Like most open source projects, though, Djangos community grew to include people from all over the globe. As Djangos community became increasingly diverse, internationalization and localization became increasingly important. Since many developers have at best a fuzzy understanding of these terms, well define them briefly.
Django璇炵敓浜庣編鍥斤紝鍜岃澶氬叾浠栫殑寮婧愯蒋浠朵竴鏍凤紝Django绀惧尯鍙戝睍涓緱鍒颁簡鍏ㄧ悆鑼冨洿鐨勬敮鎸併傛墍浠jano绀惧尯鐨勫浗闄呭寲搴旂敤鍙樺緱闈炲父閲嶈銆傜敱浜庡ぇ閲忓紑鍙戣呭鏈珷鍐呭姣旇緝鍥版儜锛屾墍浠ユ垜浠皢璇︾粏浠嬬粛銆
Internationalization refers to the process of designing programs for the potential use of any locale. This includes marking text (like UI elements and error messages) for future translation, abstracting the display of dates and times so that different local standards may be observed, providing support for differing time zones, and generally making sure that the code contains no assumptions about the location if its users. Youll often see internationalization abbreviated I18N (the number 18 refers to the number of letters omitted between the initial I and the terminal N).
鍥介檯鍖栨槸鎸囦负浜嗗湪浠讳綍鍏跺畠鍦板尯浣跨敤璇ヨ蒋浠惰岃繘琛岃璁$殑杩囩▼銆傚畠鍖呮嫭涓轰簡浠ュ悗鐨勭炕璇戣屾爣璁版枃鏈紙姣斿鐢ㄦ埛鐣岄潰鎺т欢鍜岄敊璇俊鎭瓑锛夛紝鎻愬彇鍑烘棩鏈熷拰鏃堕棿鐨勬樉绀轰互淇濊瘉鏄剧ず閬靛惊涓嶅悓鍦板尯鐨勬爣鍑嗭紝涓轰笉鍚屾椂鍖烘彁渚涙敮鎸侊紝骞朵笖鍦ㄤ竴鑸儏鍐典笅纭繚浠g爜涓笉浼氭湁鍏充簬浣跨敤鑰呮墍鍦ㄥ湴鍖虹殑鍋囪銆傛偍鍙互缁忓父鐪嬪埌鍥介檯鍖栬缂╁啓涓衡淚18N鈥(18琛ㄧずInternationlization杩欎釜鍗曡瘝棣栧瓧姣岻鍜岀粨灏惧瓧姣峃涔嬮棿鐨勫瓧姣嶆湁18涓)銆
Localization refers to the process of actually translating an internationalized program for use in a particular locale. Youll sometimes see localization abbreviated as L10N .
鏈湴鍖栨槸鎸囦娇涓涓浗闄呭寲鐨勭▼搴忎负浜嗗湪鏌愪釜鐗瑰畾鍦板尯浣跨敤鑰岃繘琛岀炕璇戠殑杩囩▼銆傛湁鏃讹紝鏈湴鍖栫缉鍐欎负 L10N 銆
Django itself is fully internationalized; all strings are marked for translation, and settings control the display of locale-dependent values like dates and times. Django also ships with over 40 different localization files. If youre not a native English speaker, theres a good chance that Django is already is translated into your primary language.
Django鏈韩鏄畬鍏ㄥ浗闄呭寲鐨勶紱鎵鏈夌殑瀛楃涓插潎琚爣璁颁负闇瑕佺炕璇戯紝鑰屼笖鍦ㄩ夐」涓彲浠ヨ缃尯鍩熼夐」锛堝鏃堕棿鍜屾棩鏈燂級鐨勬樉绀恒侱jango鏄甫鐫40涓笉鍚岀殑鏈湴鍖栨枃浠跺彂琛岀殑銆傚嵆浣挎偍涓嶆槸浠ヨ嫳璇綔涓烘瘝璇殑锛屼篃寰堟湁鍙兘Django宸茬粡琚炕璇戜负鎮ㄧ殑姣嶈浜嗐
The same internationalization framework used for these localizations is available for you to use in your own code and templates.
fprY2M <a href=”http://udwypazvwjcw.com/“>udwypazvwjcw</a>, [url=http://mhsbklajoxee.com/]mhsbklajoxee[/url], [link=http://fxqerwoknbxo.com/]fxqerwoknbxo[/link], http://xodcudwsvrdn.com/
In a nutshell, youll need to add a minimal number of hooks to your Python code and templates. These hooks are called translation strings . They tell Django, This text should be translated into the end users language, if a translation for this text is available in that language.
绠瑕佸湴璇达紝鎮ㄥ彧闇瑕佹坊鍔犲皯閲忕殑hook鍒版偍鐨凱ython浠g爜鍜屾ā鏉夸腑銆傝繖浜沨ook琚О涓衡滅炕璇戝瓧绗︿覆鈥濄傚畠浠憡璇塂jango锛屽鏋滆繖娈垫枃鏈彲浠ヨ缈昏瘧涓虹粓绔敤鎴疯瑷锛岄偅涔堝氨缈昏瘧杩欐鏂囨湰銆
Django takes care of using these hooks to translate Web applications, on the fly, according to users language preferences.
Django鏍规嵁鐢ㄦ埛鐨勮瑷鍋忓ソ鏉ヤ娇鐢ㄨ繖浜沨ook鍘荤炕璇慦eb搴旂敤绋嬪簭銆
Essentially, Django does two things:
鏈川涓婃潵璇达紝Django鍋氳繖涓や欢浜嬫儏锛
It lets developers and template authors specify which parts of their applications should be translatable.
鐢卞紑鍙戣呭拰妯℃澘鐨勪綔鑰呮寚瀹氫粬浠殑搴旂敤绋嬪簭鐨勫摢浜涢儴鍒嗘槸闇瑕佽缈昏瘧鐨勩
It uses that information to translate Web applications for particular users according to their language preferences.
Django鏍规嵁鐢ㄦ埛鐨勮瑷鍋忓ソ鏉ョ炕璇慦eb搴旂敤绋嬪簭銆
Note
澶囨敞:
Djangos translation machinery uses GNU gettext (http://www.gnu.org/software/gettext/) via the standard gettext module that comes with Python.
Django鐨勭炕璇戞満鍒舵槸浣跨敤 GNU gettext (http://www.gnu.org/software/gettext/)锛屽叿浣撲负Python鏍囧噯妯″潡 gettext 銆
If You Dont Need Internationalization:
fksZVS <a href=”http://rcecordqjdnk.com/“>rcecordqjdnk</a>, [url=http://fgdubzaohlee.com/]fgdubzaohlee[/url], [link=http://ppqbuhjowvns.com/]ppqbuhjowvns[/link], http://icuvrrikoewc.com/
Djangos internationalization hooks are enabled by default, which incurs a small bit of overhead. If you dont use internationalization, you should set USE_I18N = False in your settings file. If USE_I18N is set to False , then Django will make some optimizations so as not to load the internationalization machinery.
Django鍥介檯鍖栫殑hook榛樿鏄紑鍚殑锛岃繖鍙兘浼氱粰Django澧炲姞涓鐐圭偣璐熸媴銆傚鏋滄偍涓嶉渶瑕佸浗闄呭寲鏀寔锛岄偅涔堟偍鍙互鍦ㄦ偍鐨勮缃枃浠朵腑璁剧疆 USE_I18N = False 銆傚鏋 USE_I18N 琚涓 False 锛岄偅涔圖jango浼氳繘琛屼竴浜涗紭鍖栵紝鑰屼笉鍔犺浇鍥介檯鍖栨敮鎸佹満鍒躲
Youll probably also want to remove 'django.core.context_processors.i18n' from your TEMPLATE_CONTEXT_PROCESSORS setting.
鎮ㄤ篃鍙互浠庢偍鐨 TEMPLATE_CONTEXT_PROCESSORS 璁剧疆涓Щ闄 'django.core.context_processors.i18n' 銆
Translation strings specify This text should be translated. These strings can appear in your Python code and templates. Its your responsibility to mark translatable strings; the system can only translate strings it knows about.
缈昏瘧瀛楃涓叉寚瀹氳繖娈垫枃鏈渶瑕佽缈昏瘧銆傝繖浜涘瓧绗︿覆鍑虹幇鍦ㄦ偍鐨凱ython浠g爜鍜屾ā鏉夸腑銆傛偍闇瑕佸仛鐨勬槸鏍囪鍑鸿繖浜涚炕璇戝瓧绗︿覆锛涜岀郴缁熷彧浼氱炕璇戝嚭瀹冩墍鐭ラ亾鐨勪笢瑗裤
Specify a translation string by using the function _() . (Yes, the name of the function is the underscore character.) This function is available globally (i.e., as a built-in language); you dont have to import it.
ocf07R <a href=”http://qpopfudogomm.com/“>qpopfudogomm</a>, [url=http://zlxzyubhhfhd.com/]zlxzyubhhfhd[/url], [link=http://dbedjhghgiph.com/]dbedjhghgiph[/link], http://opgcbbdwditr.com/
In this example, the text "Welcome to my site." is marked as a translation string:
鍦ㄤ笅闈㈣繖涓緥瀛愪腑锛岃繖娈垫枃鏈 "Welcome to my site" 琚爣璁颁负缈昏瘧瀛楃涓诧細
def my_view(request): output = _("Welcome to my site.") return HttpResponse(output)
The function django.utils.translation.gettext() is identical to _() . This example is identical to the previous one:
鍑芥暟 django.utils.translation.gettext() 涓 _() 鏄浉鍚岀殑銆備笅闈㈣繖涓緥瀛愪笌鍓嶄竴涓緥瀛愭病鏈夊尯鍒細
from django.utils.translation import gettext def my_view(request): output = gettext("Welcome to my site.") return HttpResponse(output)
Most developers prefer to use _() , as its shorter.
澶у鏁板紑鍙戣呭枩娆娇鐢 _() , 鍥犱负瀹冩瘮杈冪煭灏.
Translation works on computed values. This example is identical to the previous two:
缈昏瘧瀛楃涓插浜庤鍙ュ悓鏍锋湁鏁堛備笅闈㈣繖涓緥瀛愬拰鍓嶉潰涓や釜渚嬪瓙鐩稿悓锛
def my_view(request): words = ['Welcome', 'to', 'my', 'site.'] output = _(' '.join(words)) return HttpResponse(output)
Translation works on variables. Again, heres an identical example:
缈昏瘧涔熷彲浠ュ鍙橀噺杩涜銆傚悓鏍风殑渚嬪瓙锛
def my_view(request): sentence = 'Welcome to my site.' output = _(sentence) return HttpResponse(output)
(The caveat with using variables or computed values, as in the previous two examples, is that Djangos translation-string-detecting utility, make-messages.py , wont be able to find these strings. More on make-messages later.)
锛堝浠ヤ笂涓や釜渚嬪瓙鎵绀哄湴浣跨敤鍙橀噺鎴栬鍙ワ紝闇瑕佹敞鎰忕殑涓鐐规槸Django鐨勭炕璇戝瓧绗︿覆妫娴嬪伐鍏凤紝 make-messages.py 锛屼笉鑳芥壘鍒拌繖浜涘瓧绗︿覆銆傚湪鍚庨潰鐨勫唴瀹逛腑浼氱户缁璁鸿繖涓棶棰樸傦級
The strings you pass to _() or gettext() can take placeholders, specified with Pythons standard named-string interpolation syntax, for example:
浼犻掔粰 _() 鎴 gettext() 鐨勫瓧绗︿覆鍙互鎺ュ彈鐢盤ython鏍囧噯瀛楀吀鍨嬪璞$殑鏍煎紡鍖栧瓧绗︿覆琛ㄨ揪寮忔寚瀹氱殑鍗犱綅绗︼紝姣斿锛
def my_view(request, n): output = _('%(name)s is my name.') % {'name': n} return HttpResponse(output)
This technique lets language-specific translations reorder the placeholder text. For example, an English translation may be "Adrian is my name." , while a Spanish translation may be "Me llamo Adrian." , with the placeholder (the name) placed after the translated text instead of before it.
杩欓」鎶鏈娇寰楃壒瀹氳瑷鐨勮瘧鏂囧彲浠ュ杩欐鏂囨湰杩涜閲嶆柊鎺掑簭銆傛瘮濡傦紝涓娈垫枃鏈殑鑻辫缈昏瘧涓 "Adrian is my name." 锛岃岃タ鐝墮璇炕璇戜负 "Me llamo Adrian." 锛屾鏃讹紝鍗犱綅绗︼紙鍗硁ame锛夊疄鍦ㄨ缈昏瘧鐨勬枃鏈箣鍓嶈屼笉鏄箣鍚庛
For this reason, you should use named-string interpolation (e.g., %(name)s ) instead of positional interpolation (e.g., %s or %d ). If you use positional interpolation, translations wont be able to reorder placeholder text.
姝e洜涓哄姝わ紝鎮ㄥ簲璇ヤ娇鐢ㄥ瓧鍏稿瀷瀵硅薄鐨勬牸寮忓寲瀛楃涓诧紙姣斿锛 %(name)s 锛夛紝鑰屼笉鏄拡瀵逛綅缃殑鏍煎紡鍖栧瓧绗︿覆锛堟瘮濡傦紝 %s 鎴 %d 锛夈傚鏋滄偍浣跨敤閽堝浣嶇疆鐨勬牸寮忓寲瀛楃涓诧紝缈昏瘧鏈哄埗灏嗘棤娉曢噸鏂板畨鎺掑寘鍚崰浣嶇鐨勬枃鏈
Use the function django.utils.translation.gettext_noop() to mark a string as a translation string without actually translating it at that moment. Strings thus marked arent translated until the last possible moment.
aqx6dN <a href=”http://ngytacoffksa.com/“>ngytacoffksa</a>, [url=http://frgtlggamlkr.com/]frgtlggamlkr[/url], [link=http://rzddwvkeesje.com/]rzddwvkeesje[/link], http://tsmbjzujsbqn.com/
Use this approach if you have constant strings that should be stored in the original language such as strings in a database but should be translated at the last possible point in time, such as when the string is presented to the user.
浣跨敤杩欑鏂规硶鐨勭幆澧冩槸锛屾湁瀛楃涓插繀椤讳互鍘熷璇█鐨勫舰寮忓瓨鍌紙濡傚偍瀛樺湪鏁版嵁搴撲腑鐨勫瓧绗︿覆锛夎屽湪鏈鍚庨渶瑕佽缈昏瘧鍑烘潵锛屽褰撳叾鍦ㄧ敤鎴峰墠鏄剧ず鍑烘潵鏃躲
Use the function django.utils.translation.gettext_lazy() to translate strings lazily when the value is accessed rather than when the gettext_lazy() function is called.
浣跨敤 django.utils.translation.gettext_lazy() 鍑芥暟锛屼娇寰楀叾涓殑鍊煎彧鏈夊湪璁块棶鏃舵墠浼氳缈昏瘧锛岃屼笉鏄湪 gettext_lazy() 琚皟鐢ㄦ椂缈昏瘧銆
For example, to mark a fieldss help_text attribute as translatable, do the following:
姣斿锛岃鏍囪 help_text 鍒楁槸闇瑕佺炕璇戠殑锛屽彲浠ヨ繖涔堝仛锛
from django.utils.translation import gettext_lazy class MyThing(models.Model): name = models.CharField(help_text=gettext_lazy('This is the help text'))
In this example, gettext_lazy() stores a lazy reference to the string not the actual translation. The translation itself will be done when the string is used in a string context, such as template rendering on the Django admin site.
鍦ㄨ繖涓緥瀛愪腑锛 gettext_lazy() 灏嗗瓧绗︿覆浣滀负鎯版х炕璇戝瓧绗︿覆瀛樺偍锛屾鏃跺苟娌℃湁杩涜缈昏瘧銆傜炕璇戝伐浣滃皢鍦ㄥ瓧绗︿覆鍦ㄥ瓧绗︿覆涓婁笅鏂囦腑琚敤鍒版椂杩涜锛屾瘮濡傚湪Django绠$悊椤甸潰鎻愪氦妯℃澘鏃躲
If you dont like the verbose name gettext_lazy , you can just alias it as _ (underscore), like so:
濡傛灉瑙夊緱 gettext_lazy 澶繃鍐楅暱锛屽彲浠ョ敤 _ 锛堜笅鍒掔嚎锛変綔涓哄埆鍚嶏紝灏卞儚杩欐牱锛
from django.utils.translation import gettext_lazy as _ class MyThing(models.Model): name = models.CharField(help_text=_('This is the help text'))
Always use lazy translations in Django models (otherwise they wont be translated correctly on a per-user basis). And its a good idea to add translations for the field names and table names, too. This means writing explicit verbose_name and verbose_name_plural options in the Meta class:
鍦―jango妯″瀷涓渶濂戒竴鐩翠娇鐢ㄦ儼鎬х炕璇戯紙闄ら潪杩欐牱缈昏瘧鐨勭粨鏋滄棤娉曟纭湴鏄剧ず锛夈傚悓鏃讹紝瀵逛簬鍒楀悕鍜岃〃鍚嶆渶濂戒篃鑳借繘琛岀炕璇戙傝繖闇瑕佸湪 Meta 涓槑纭 verbose_name 鍜 verbose_name_plural 鐨勫硷細
from django.utils.translation import gettext_lazy as _ class MyThing(models.Model): name = models.CharField(_('name'), help_text=_('This is the help text')) class Meta: verbose_name = _('my thing') verbose_name_plural = _('mythings')
Use the function django.utils.translation.ngettext() to specify messages that have different singular and plural forms, for example:
浣跨敤 django.utils.translation.ngettext() 鍑芥暟鏉ユ寚瀹氭湁鍗曟暟鍜屽鏁板舰寮忎箣鍒嗙殑淇℃伅锛屾瘮濡傦細
from django.utils.translation import ngettext def hello_world(request, count): page = ngettext( 'there is %(count)d object', 'there are %(count)d objects', count ) % {'count': count} return HttpResponse(page)
ngettext takes three arguments: the singular translation string, the plural translation string, and the number of objects (which is passed to the translation languages as the count variable).
ngettext 鍑芥暟鍖呮嫭涓変釜鍙傛暟锛氬崟鏁板舰寮忕殑缈昏瘧瀛楃涓诧紝澶嶆暟褰㈠紡鐨勭炕璇戝瓧绗︿覆锛屽拰瀵硅薄鐨勪釜鏁帮紙灏嗕互 count 鍙橀噺浼犻掔粰闇瑕佺炕璇戠殑璇█锛夈
7jEPL5 <a href=”http://siswbqyeiacu.com/“>siswbqyeiacu</a>, [url=http://wggfxnxdjnmc.com/]wggfxnxdjnmc[/url], [link=http://smzrnicwasqa.com/]smzrnicwasqa[/link], http://xqxscmgtbhpc.com/
Using translations in Django templates uses two template tags and a slightly different syntax than in Python code. To give your template access to these tags, put {% load i18n %} toward the top of your template.
Django妯℃澘浣跨敤涓ょ妯℃澘鏍囩锛屼笖璇硶鏍煎紡涓嶱ython浠g爜鏈変簺璁镐笉鍚屻備负浜嗕娇寰楁ā鏉胯闂埌鏍囩锛岄渶瑕佸皢 {% load i18n %} 鏀惧湪妯℃澘鏈鍓嶉潰銆
The {% trans %} template tag marks a string for translations:
{% trans %} 妯℃澘鏍囩鏍囪闇瑕佺炕璇戠殑瀛楃涓诧細
<title>{% trans "This is the title." %}</title>
If you only want to mark a value for translation, but translate it later, use the noop option:
濡傛灉鍙渶瑕佹爣璁板瓧绗︿覆鑰屼互鍚庡啀缈昏瘧锛屽彲浠ヤ娇鐢 noop 閫夐」锛
<title>{% trans "value" noop %}</title>
Its not possible to use template variables in {% trans %} only constant strings, in single or double quotes, are allowed. If your translations require variables (placeholders), use {% blocktrans %} , for example:
鍦 {% trans %} 涓笉鍏佽浣跨敤妯℃澘涓殑鍙橀噺锛屽彧鑳戒娇鐢ㄥ崟寮曞彿鎴栧弻寮曞彿涓殑瀛楃涓层傚鏋滅炕璇戞椂闇瑕佺敤鍒板彉閲忥紙鍗犱綅绗︼級锛屽彲浠ヤ娇鐢 {% blocktrans %} 锛屾瘮濡傦細
{% blocktrans %}This will have {{ value }} inside.{% endblocktrans %}
To translate a template expression say, using template filters you need to bind the expression to a local variable for use within the translation block:
浣跨敤妯℃澘杩囨护鍣ㄦ潵缈昏瘧涓涓ā鏉胯〃杈惧紡锛岄渶瑕佸湪缈昏瘧鐨勮繖娈垫枃鏈腑灏嗚〃杈惧紡缁戝畾鍒颁竴涓湰鍦板彉閲忎腑锛
{% blocktrans with value|filter as myvar %} This will have {{ myvar }} inside. {% endblocktrans %}
If you need to bind more than one expression inside a blocktrans tag, separate the pieces with and :
qTgtvg <a href=”http://cbniwxkldxuc.com/“>cbniwxkldxuc</a>, [url=http://lelxwibpyhqi.com/]lelxwibpyhqi[/url], [link=http://climlfoemmpl.com/]climlfoemmpl[/link], http://mmxmuaxedeha.com/
{% blocktrans with book|title as book_t and author|title as author_t %} This is {{ book_t }} by {{ author_t }} {% endblocktrans %}
To pluralize, specify both the singular and plural forms with the {% plural %} tag, which appears within {% blocktrans %} and {% endblocktrans %} , for example:
涓轰簡琛ㄧず鍗曞鏁扮浉鍏崇殑鍐呭锛岄渶瑕佸湪 {% blocktrans %} 鍜 {% endblocktrans %} 涔嬮棿浣跨敤 {% plural %} 鏍囩鏉ユ寚瀹氬崟澶嶆暟褰㈠紡锛屼緥濡傦細
{% blocktrans count list|length as counter %} There is only one {{ name }} object. {% plural %} There are {{ counter }} {{ name }} objects. {% endblocktrans %}
Internally, all block and inline translations use the appropriate gettext /ngettext call.
鍏跺唴鍦ㄦ満鍒舵槸锛屾墍鏈夌殑鍧楀拰鍐呭祵缈昏瘧璋冪敤鐩稿簲鐨 gettext 鎴 ngettext 銆
When you use RequestContext (see Chapter 10), your templates have access to three translation-specific variables:
浣跨敤 RequestContext 锛堣绗10绔狅級鏃讹紝妯℃澘鍙互璁块棶涓変釜閽堝缈昏瘧鐨勫彉閲忥細
{{ LANGUAGES }} is a list of tuples in which the first element is the language code and the second is the language name (in that language).
{{ LANGUAGES }} 鏄竴绯诲垪鍏冪粍缁勬垚鐨勫垪琛紝姣忎釜鍏冪粍鐨勭涓涓厓绱犳槸璇█浠g爜锛岀浜屼釜鍏冪礌鏄敤璇ヨ瑷琛ㄧず鐨勮瑷鍚嶇О銆
{{ LANGUAGE_CODE }} is the current users preferred language, as a string (e.g., en-us ). (See the How Django Discovers Language Preference section for more information.)
{{ LANGUAGE_CODE }} 鏄互瀛楃涓茶〃绀虹殑褰撳墠鐢ㄦ埛鍋忓ソ璇█锛堜緥濡傦紝 en-us 锛夈傦紙璇﹁ Django 濡備綍纭畾璇█鍋忓ソ銆傦級
{{ LANGUAGE_BIDI }} is the current languages writing system. If True , its a right-to-left language (e.g., Hebrew, Arabic). If False , its a left-to-right language (e.g., English, French, German).
{{ LANGUAGE_BIDI }} 鏄綋鍓嶈瑷鐨勪功鍐欐柟寮忋傝嫢璁句负 True 锛屽垯璇ヨ瑷涔﹀啓鏂瑰悜涓轰粠鍙冲埌宸︼紙濡傚笇浼潵璇拰闃挎媺浼锛夛紱鑻ヨ涓 False 锛屽垯璇ヨ瑷涔﹀啓鏂瑰悜涓轰粠宸﹀埌鍙筹紙濡傝嫳璇佹硶璇拰寰疯锛夈
You can also load these values using template tags:
浣犱篃鍙互閫氳繃浣跨敤妯℃澘鏍囩鏉ュ姞杞借繖浜涘彉閲忥細
{% load i18n %} {% get_current_language as LANGUAGE_CODE %} {% get_available_languages as LANGUAGES %} {% get_current_language_bidi as LANGUAGE_BIDI %}
Translation hooks are also available within any template block tag that accepts constant strings. In those cases, just use _() syntax to specify a translation string, for example:
缈昏瘧鐨刪ook鍦ㄤ换浣曟帴鍙楀父閲忓瓧绗︿覆鐨勬ā鏉垮潡鏍囩鍐呬篃鏄彲浠ヤ娇鐢ㄧ殑銆傛鏃讹紝浣跨敤 _() 琛ㄨ揪寮忔潵鎸囧畾缈昏瘧瀛楃涓诧紝渚嬪锛
{% some_special_tag _("Page not found") value|yesno:_("yes,no") %}
In this case, both the tag and the filter will see the already-translated string (i.e., the string is translated before being passed to the tag handler functions), so they dont need to be aware of translations.
OQy5ZT <a href=”http://zicjwleradwz.com/“>zicjwleradwz</a>, [url=http://klbbjyqcrtdt.com/]klbbjyqcrtdt[/url], [link=http://adylkqwpfagm.com/]adylkqwpfagm[/link], http://bghiparjlrvr.com/
鍒涘缓璇█鏂囦欢
Once youve tagged your strings for later translation, you need to write (or obtain) the language translations themselves. In this section we explain how that works.
褰撲綘鏍囪浜嗙炕璇戝瓧绗︿覆锛屼綘灏遍渶瑕佸啓鍑猴紙鎴栬幏鍙栧凡鏈夌殑锛夊搴旂殑璇█缈昏瘧淇℃伅銆傚湪杩欎竴鑺備腑鎴戜滑灏嗚В閲婂浣曚娇瀹冭捣浣滅敤銆
鍒涘缓淇℃伅鏂囦欢
The first step is to create a message file for a new language. A message file is a plain-text file representing a single language that contains all available translation strings and how they should be represented in the given language. Message files have a .po file extension.
绗竴姝ワ紝灏辨槸涓轰竴绉嶈瑷鍒涘缓涓涓俊鎭枃浠躲備竴涓俊鎭枃浠舵槸鍖呭惈浜嗘煇涓璇█缈昏瘧瀛楃涓插拰瀵硅繖浜涘瓧绗︿覆鐨勭炕璇戠殑涓涓枃鏈枃浠躲備俊鎭枃浠朵互 .po 涓哄悗缂鍚嶃
Django comes with a tool, bin/make-messages.py , that automates the creation and maintenance of these files.
Django涓甫鏈変竴涓伐鍏凤紝 bin/make-messages.py 锛屽畠瀹屾垚浜嗚繖浜涙枃浠剁殑鍒涘缓鍜岀淮鎶ゅ伐浣溿
To create or update a message file, run this command:
杩愯浠ヤ笅鍛戒护鏉ュ垱寤烘垨鏇存柊涓涓俊鎭枃浠讹細
bin/make-messages.py -l de
where de is the language code for the message file you want to create. The language code, in this case, is in locale format. For example, its pt_BR for Brazilian Portuguese and de_AT for Austrian German. Take a look at thelanguage codes in the django/conf/locale/ directory to see which languages are currently supported.
鍏朵腑 de 鏄墍鍒涘缓鐨勪俊鎭枃浠剁殑璇█浠g爜銆傚湪杩欓噷锛岃瑷浠g爜鏄互鏈湴鏍煎紡缁欏嚭鐨勩備緥濡傦紝宸磋タ鍦板尯鐨勮憽钀勭墮璇负 pt_BR 锛屾境澶у埄浜氬湴鍖虹殑寰疯涓 de_AT 銆傚彲鏌ョ湅 django/conf/locale 鐩綍鑾峰彇Django鎵鏀寔鐨勮瑷浠g爜銆
The script should be run from one of three places:
杩欐鑴氭湰搴旇鍦ㄤ笁澶勪箣涓杩愯锛
The root django directory (not a Subversion checkout, but the one that is linked to via $PYTHONPATH or is located somewhere on that path)
django 鏍圭洰褰曪紙涓嶆槸Subversion妫鍑虹洰褰曪紝鑰屾槸閫氳繃 $PYTHONPATH 閾炬帴鎴栦綅浜庤璺緞鐨勬煇澶勶級
The root directory of your Django project
Django椤圭洰鏍圭洰褰
The root directory of your Django application
Django搴旂敤绋嬪簭鏍圭洰褰
The script runs over the entire tree it is run on and pulls out all strings marked for translation. It creates (or updates) a message file in the directory conf/locale . In the de example, the file will be conf/locale/de/LC_MESSAGES/django.po .
璇ヨ剼鏈綔鐢ㄤ簬鎵鍦ㄧ殑鏁翠釜鐩綍鏍戯紝骞朵笖鎶藉彇鎵鏈夎鏍囪鐨勫瓧绗︿覆浠ヨ繘琛岀炕璇戙傚畠鍦 conf/locale 鐩綍涓嬪垱寤猴紙鎴栨洿鏂帮級浜嗕竴涓俊鎭枃浠躲傚湪涓婇潰杩欎釜渚嬪瓙涓紝杩欎釜淇℃伅鏂囦欢鏄 conf/locale/de/LC_MESSAGES/django.po 銆
If run over your project source tree or your application source tree, it will do the same, but the location of the locale directory is locale/LANG/LC_MESSAGES (note the missing conf prefix). The first time you run it on your tree youll need to create the locale directory.
杩愯浜庨」鐩簮鐮佹爲鎴栧簲鐢ㄧ▼搴忔簮鐮佹爲涓嬫椂锛岃鑴氭湰瀹屾垚鍚屾牱鐨勫姛鑳斤紝浣嗘槸姝ゆ椂locale鐩綍鐨勪綅缃负 locale/LANG/LC_MESSAGES 锛堟敞鎰忔病鏈塦`conf``鍓嶇紑锛夈傚湪绗竴娆¤繍琛屾椂闇瑕佸垱寤 locale 鐩綍銆
No gettext?
娌℃湁gettext?
If you dont have the gettext utilities installed, make-messages.py will create empty files. If thats the case, either install the gettext utilities or just copy the English message file (conf/locale/en/LC_MESSAGES/django.po ) and use it as a starting point; its just an empty translation file.
濡傛灉娌℃湁瀹夎 gettext 缁勪欢锛 make-messages.py 灏嗕細鍒涘缓绌虹櫧鏂囦欢銆傝繖绉嶆儏鍐典笅锛屽畨瑁 gettext 缁勪欢鎴栧彧鏄鍒惰嫳璇俊鎭枃浠( conf/locale/en/LC_MESSAGES/django.po )鏉ヤ綔涓轰竴涓捣鐐癸紱鍙槸涓涓┖鐧界殑缈昏瘧淇℃伅鏂囦欢鑰屽凡銆
The format of .po files is straightforward. Each .po file contains a small bit of metadata, such as the translation maintainers contact information, but the bulk of the file is a list of messages simple mappings between translation strings and the actual translated text for the particular language.
.po 鏂囦欢鏍煎紡寰堢洿瑙傘傛瘡涓 .po 鏂囦欢鍖呭惈涓灏忛儴鍒嗙殑鍏冩暟鎹紝姣斿缈昏瘧缁存姢浜哄憳鐨勮仈绯讳俊鎭紝鑰屾枃浠剁殑澶ч儴鍒嗗唴瀹规槸绠鍗曠殑缈昏瘧瀛楃涓插拰瀵瑰簲璇█缈昏瘧缁撴灉鐨勬槧灏勫叧绯荤殑鍒楄〃銆
For example, if your Django application contains a translation string for the text "Welcome to my site." , like so:
涓句釜渚嬪瓙锛屽鏋淒jango搴旂敤绋嬪簭鍖呮嫭涓涓 "Welcome to my site." 鐨勭炕璇戝瓧绗︿覆锛屽儚杩欐牱锛
_("Welcome to my site.")
then make-messages.py will have created a .po file containing the following snippet a message:
make-message.py 灏嗗垱寤轰竴涓寘鍚互涓嬬墖娈电殑 .po 鏂囦欢锛
#: path/to/python/module.py:23 msgid "Welcome to my site." msgstr ""
A quick explanation is in order:
鎸夐『搴忕畝鍗曡В閲婁竴涓嬶細
msgid is the translation string, which appears in the source. Dont change it.
msgid 鏄湪婧愭枃浠朵腑鍑虹幇鐨勭炕璇戝瓧绗︿覆銆備笉瑕佸仛鏀瑰姩銆
msgstr is where you put the language-specific translation. It starts out empty, so its your responsibility to change it. Make sure you keep the quotes around your translation.
msgstr 鏄浉搴旇瑷鐨勭炕璇戠粨鏋溿傚垰鍒涘缓鏃跺畠鍙槸绌哄瓧绗︿覆锛屾鏃跺氨闇瑕佷綘鏉ュ畬鎴愬畠銆傛敞鎰忎笉瑕佷涪鎺夎鍙ュ墠鍚庣殑寮曞彿銆
As a convenience, each message includes the file name and line number from which the translation string was gleaned.
鏂逛究璧疯锛屾瘡涓鏉′俊鎭寘鍚簡缈昏瘧瀛楃涓叉墍鍦ㄦ枃浠剁殑鏂囦欢鍚嶅拰琛屾暟銆
Long messages are a special case. The first string directly after msgstr (or msgid ) is an empty string. Then the content itself will be written over the next few lines as one string per line. Those strings are directly concatenated. Dont forget trailing spaces within the strings; otherwise, theyll be tacked together without whitespace!
瀵逛簬姣旇緝闀跨殑淇℃伅涔熸湁鍏跺鐞嗘柟娉曘 msgstr 锛堟垨 msgid 锛夊悗绱ц窡鐫鐨勫瓧绗︿覆涓轰竴涓┖瀛楃涓层傜劧鍚庣湡姝g殑鍐呭鍦ㄥ叾涓嬮潰鐨勫嚑琛屻傝繖浜涘瓧绗︿覆浼氳鐩存帴杩炲湪涓璧枫傚悓鏃讹紝涓嶈蹇樹簡瀛楃涓叉湯灏剧殑绌烘牸锛屽洜涓哄畠浠細涓嶅姞绌烘牸鍦拌繛鍒颁竴璧枫
For example, heres a multiline translation (taken from the Spanish localization that ships with Django):
姣斿锛屼互涓嬫槸涓涓琛岀炕璇戯紙鍙栬嚜闅廌jango鍙戣鐨勮タ鐝墮鏈湴鍖栨枃浠讹級锛
msgid "" "There's been an error. It's been reported to the site administrators via e-" "mail and should be fixed shortly. Thanks for your patience." msgstr "" "Ha ocurrido un error. Se ha informado a los administradores del sitio " "mediante correo electrnico y debera arreglarse en breve. Gracias por su " "paciencia."
Note the trailing spaces.
娉ㄦ剰姣忎竴琛岀粨灏剧殑绌烘牸銆
Mind Your Charset
娉ㄦ剰瀛楃闆
When creating a .po file with your favorite text editor, first edit the charset line (search for "CHARSET" ) and set it to the charset youll be using to edit the content. Generally, UTF-8 should work for most languages, but gettext should handle any charset you throw at it.
褰撲綘浣跨敤鍠滅埍鐨勬枃鏈紪杈戝櫒鍒涘缓 .po 鏂囦欢鏃讹紝棣栧厛璇风紪杈戝瓧绗﹂泦琛岋紙鎼滅储 "CHARSET" 锛夛紝骞跺皢鍏惰涓轰綘灏嗕娇鐢ㄧ殑瀛楃闆嗐備竴鑸鏉ワ紝UTF-8瀵圭粷澶у鏁拌瑷鏈夋晥锛屼笉杩 gettext 浼氬鐞嗕换浣曚綘鎵浣跨敤鐨勫瓧绗﹂泦銆
To reexamine all source code and templates for new translation strings and update all message files for all languages, run this:
鑻ヨ瀵规柊鍒涘缓鐨勭炕璇戝瓧绗︿覆鏍¢獙鎵鏈夌殑婧愪唬鐮佸拰妯℃澘涓紝骞朵笖鏇存柊鎵鏈夎瑷鐨勪俊鎭枃浠讹紝鍙互杩愯浠ヤ笅鍛戒护锛
make-messages.py -a
After you create your message file, and each time you make changes to it, youll need to compile it into a more efficient form, for use by gettext . Do this with the bin/compile-messages.py utility.
鍒涘缓淇℃伅鏂囦欢涔嬪悗锛屾瘡娆″鍏跺仛浜嗕慨鏀癸紝閮介渶瑕佸皢瀹冮噸鏂扮紪璇戞垚涓绉嶆洿鏈夋晥鐜囩殑褰㈠紡锛屼緵 gettext 浣跨敤銆備娇鐢 `` bin/compile-messages.py `` 鏉ュ畬鎴愯繖椤瑰伐浣溿
This tool runs over all available .po files and creates .mo files, which are binary files optimized for use by gettext . In the same directory from which you ran make-messages.py , run compile-messages.py like this:
杩欎釜宸ュ叿浣滅敤浜庢墍鏈夋湁鏁堢殑 .po 鏂囦欢锛屽垱寤轰紭鍖栬繃鐨勪簩杩涘埗 .mo 鏂囦欢渚 gettext 浣跨敤銆傚湪杩愯 make-messages.py 鐨勫悓涓鐩綍涓嬶紝杩愯 compile-messages.py 锛
bin/compile-messages.py
Thats it. Your translations are ready for use.
灏辨槸杩欐牱浜嗐備綘鐨勭炕璇戞垚鏋滃凡缁忓彲浠ヤ娇鐢ㄤ簡銆
Django濡備綍澶勭悊璇█鍋忓ソ
Once youve prepared your translations or, if you just want to use the translations that are included with Django youll just need to activate translation for your application.
涓鏃︿綘鍑嗗濂戒簡缈昏瘧锛屽鏋滃笇鏈涘湪Django涓娇鐢紝閭d箞鍙渶瑕佹縺娲昏繖浜涚炕璇戝嵆鍙
Behind the scenes, Django has a very flexible model of deciding which language should be used installation-wide, for a particular user, or both.
鍦ㄨ繖浜涘姛鑳借儗鍚庯紝Django鎷ユ湁涓涓伒娲荤殑妯″瀷鏉ョ‘瀹氬湪瀹夎鍜屼娇鐢ㄥ簲鐢ㄧ▼搴忕殑杩囩▼涓夋嫨浣跨敤鐨勮瑷銆
To set an installation-wide language preference, set LANGUAGE_CODE in your settings file. Django uses this language as the default translation the final attempt if no other translator finds a translation.
鑻ヨ鍦ㄦ暣涓畨瑁呭拰浣跨敤杩囩▼涓‘瀹氳瑷鍋忓ソ锛屽氨瑕佸湪璁剧疆鏂囦欢涓缃 LANGUAGE_CODE 銆侱jango灏嗙敤鎸囧畾鐨勮瑷鏉ヨ繘琛岀炕璇戯紝濡傛灉娌℃湁鍏跺畠鐨勭炕璇戝櫒鍙戠幇瑕佽繘琛岀炕璇戠殑璇彞锛岃繖灏辨槸鏈鍚庝竴姝ヤ簡銆
If all you want to do is run Django with your native language, and a language file is available for your language, simply set LANGUAGE_CODE .
濡傛灉浣犲彧鏄兂瑕佺敤鏈湴璇█鏉ヨ繍琛孌jango锛屽苟涓旇璇█鐨勮瑷鏂囦欢瀛樺湪锛屽彧闇瑕佺畝鍗曞湴璁剧疆 LANGUAGE_CODE 鍗冲彲銆
If you want to let each individual user specify the language he or she prefers, use LocaleMiddleware . LocaleMiddleware enables language selection based on data from the request. It customizes content for each user.
濡傛灉瑕佽姣忎竴涓娇鐢ㄨ呭悇鑷寚瀹氳瑷鍋忓ソ锛屽氨闇瑕佷娇鐢 LocaleMiddleware 銆 LocaleMiddleware 浣垮緱Django鍩轰簬璇锋眰鐨勬暟鎹繘琛岃瑷閫夋嫨锛屼粠鑰屼负姣忎竴浣嶇敤鎴峰畾鍒跺唴瀹广
To use LocaleMiddleware , add 'django.middleware.locale.LocaleMiddleware' to your MIDDLEWARE_CLASSES setting. Because middleware order matters, you should follow these guidelines:
浣跨敤 LocaleMiddleware 闇瑕佸湪 MIDDLEWARE_CLASSES 璁剧疆涓鍔 'django.middleware.locale.LocaleMiddleware' 銆備腑闂翠欢鐨勯『搴忔槸鏈夊奖鍝嶇殑锛屾渶濂芥寜鐓т緷鐓т互涓嬭姹傦細
Make sure its among the first middleware classes installed.
淇濊瘉瀹冩槸绗竴鎵瑰畨瑁呯殑涓棿浠剁被銆
It should come after SessionMiddleware , because LocaleMiddleware makes use of session data.
鍥犱负 LocalMiddleware 瑕佺敤鍒皊ession鏁版嵁锛屾墍浠ラ渶瑕佹斁鍦 SessionMiddleware 涔嬪悗銆
If you use CacheMiddleware , put LocaleMiddleware after it (otherwise users could get cached content from the wrong locale).
濡傛灉浣跨敤浜 CacheMiddleware 锛屽皢 LocaleMiddleware 鏀惧湪 CacheMiddleware 涔嬪悗锛堝惁鍒欑敤鎴峰彲鑳戒細浠庨敊璇殑鏈湴鍖栨枃浠朵腑鍙栧緱缂撳啿鏁版嵁锛夈
For example, your MIDDLEWARE_CLASSES might look like this:
渚嬪锛 MIDDLE_CLASSES 鍙兘浼氭槸濡傛锛
MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.locale.LocaleMiddleware' )
LocaleMiddleware tries to determine the users language preference by following this algorithm:
LocaleMiddleware 鎸夌収濡備笅绠楁硶纭畾鐢ㄦ埛鐨勮瑷:
First, it looks for a django_language key in the current users session.
棣栧厛锛屽湪褰撳墠鐢ㄦ埛 session 鐨勪腑鏌ユ壘閿 django_language 鐨勫硷紱
Failing that, it looks for a cookie called django_language .
濡傛灉澶辫触鐨勮瘽锛屾帴鐫鏌ユ壘鍚嶄负 django_language 鐨 cookie 锛
Failing that, it looks at the Accept-Language HTTP header. This header is sent by your browser and tells the server which language(s) you prefer, in order of priority. Django tries each language in the header until it finds one with available translations.
杩樻槸澶辫触鐨勮瘽锛屽氨鍦 HTTP 璇锋眰澶撮儴鏌ユ壘 Accept-Language 鍏抽敭瀛楃殑鍊硷紝璇ュ叧閿瓧鏄綘鐨勬祻瑙堝櫒鍙戦佺殑锛屾寜浼樺厛椤哄簭鍛婅瘔鏈嶅姟鍣ㄤ綘鐨勮瑷鍋忓ソ銆侱jango 浼氭牴鎹繖浜涜瑷鐨勯『搴忛愪竴鎼滅储鐩村埌鍙戠幇鍙敤鐨勭炕璇戯紱
Failing that, it uses the global LANGUAGE_CODE setting.
浠ヤ笂閮藉け璐ヤ簡鐨勮瘽, 灏变娇鐢ㄥ叏灞鐨 LANGUAGE_CODE 璁惧畾鍊笺
In each of these places, the language preference is expected to be in the standard language format, as a string. For example, Brazilian Portuguese is pt-br . If a base language is available but the sub-language specified is not, Django uses the base language. For example, if a user specifies de-at (Austrian German) but Django only has de available, Django uses de .
鍦ㄤ笂杩版瘡涓澶勶紝璇█鍋忓ソ搴斾綔涓哄瓧绗︿覆锛屼互鏍囧噯鐨勮瑷鏍煎紡鍑虹幇銆傛瘮濡傦紝宸磋タ鍦板尯鐨勮憽钀勭墮璇〃绀轰负 pt-br 銆傚鏋淒jango涓彧鏈夊熀鏈瑷鑰屾病鏈夊叾琛嶇敓鐨勫瓧璇█鐨勮瘽锛孌jango灏嗗彧鏄敤鍩烘湰璇█銆傛瘮濡傦紝濡傛灉鐢ㄦ埛鎸囧畾浜 de-at 锛堟境寮忓痉璇級浣咲jango鍙湁閽堝 de 鐨勭炕璇戯紝閭d箞 de 浼氳閫夌敤銆
Only languages listed in the LANGUAGES setting can be selected. If you want to restrict the language selection to a subset of provided languages (because your application doesnt provide all those languages), set your LANGUAGES setting to a list of languages, for example:
鍙湁鍦 LANGUAGES 璁剧疆涓垪鍑虹殑璇█鎵嶈兘琚夌敤銆傝嫢甯屾湜灏嗚瑷闄愬埗涓烘墍鎻愪緵璇█涓殑鏌愪簺锛堝洜涓哄簲鐢ㄧ▼搴忓苟涓嶆彁渚涙墍鏈夎瑷鐨勮〃绀猴級锛屽垯灏 LANGUAGES 璁剧疆涓烘墍甯屾湜鎻愪緵璇█鐨勫垪琛紝渚嬪锛
LANGUAGES = ( ('de', _('German')), ('en', _('English')), )
This example restricts languages that are available for automatic selection to German and English (and any sub-language, like de-ch or en-us ).
涓婇潰杩欎釜渚嬪瓙闄愬埗浜嗚瑷鍋忓ソ鍙兘鏄痉璇拰鑻辫锛堝寘鎷畠浠殑瀛愯瑷锛屽 de-ch 鍜 en-us 锛夈
If you define a custom LANGUAGES , its OK to mark the languages as translation strings but use a dummy gettext() function, not the one in django.utils.translation . You should never import django.utils.translation from within your settings file, because that module itself depends on the settings, and that would cause a circular import.
濡傛灉鑷畾涔変簡 LANGUAGES 锛屽皢璇█鏍囪涓虹炕璇戝瓧绗︿覆鏄彲浠ョ殑锛屼絾鏄紝璇蜂笉瑕佷娇鐢 django.utils.translation 涓殑 gettext() 锛堝喅涓嶈鍦╯ettings鏂囦欢涓鍏 django.utils.translation 锛屽洜涓鸿繖涓ā鍧楁湰韬槸渚濊禆浜巗ettings锛岃繖鏍峰仛浼氬鑷存棤闄愬惊鐜級锛岃屾槸浣跨敤涓涓滆櫄鏋勭殑鈥 gettext() 銆
The solution is to use a dummy gettext() function. Heres a sample settings file:
瑙e喅鏂规灏辨槸浣跨敤涓涓滆櫄鍋囩殑鈥 gettext() 銆備互涓嬫槸涓涓猻ettings鏂囦欢鐨勪緥瀛愶細
_ = lambda s: s LANGUAGES = ( ('de', _('German')), ('en', _('English')), )
With this arrangement, make-messages.py will still find and mark these strings for translation, but the translation wont happen at runtime, so youll have to remember to wrap the languages in the real gettext() in any code that uses LANGUAGES at runtime.
杩欐牱鍋氱殑璇濓紝 make-messages.py 浠嶄細瀵绘壘骞舵爣璁板嚭灏嗚琚炕璇戠殑杩欎簺瀛楃涓诧紝浣嗙炕璇戜笉浼氬啀杩愯鏃惰繘琛岋紝鏁呰岄渶瑕佸湪浠讳綍浣跨敤 LANGUAGES 鐨勪唬鐮佷腑鐢ㄢ滅湡瀹炵殑鈥 gettext() 鏉ヤ慨楗拌繖浜涜瑷銆
The LocaleMiddleware can only select languages for which there is a Django-provided base translation. If you want to provide translations for your application that arent already in the set of translations in Djangos source tree, youll want to provide at least basic translations for that language. For example, Django uses technical message IDs to translate date formats and time formats so you will need at least those translations for the system to work correctly.
LocaleMiddleware 鍙兘閫夋嫨閭d簺Django宸茬粡鎻愪緵浜嗗熀纭缈昏瘧鐨勮瑷銆傚鏋滄兂瑕佸湪搴旂敤绋嬪簭涓Django涓繕娌℃湁鍩虹缈昏瘧鐨勮瑷鎻愪緵缈昏瘧锛岄偅涔堝繀椤昏嚦灏戝厛鎻愪緵璇ヨ瑷鐨勫熀鏈殑缈昏瘧銆備緥濡傦紝Django浣跨敤鐗瑰畾鐨勪俊鎭疘D鏉ョ炕璇戞棩鏈熷拰鏃堕棿鏍煎紡锛屾晠瑕佽绯荤粺姝e父宸ヤ綔锛岃嚦灏戣鎻愪緵杩欎簺鍩烘湰鐨勭炕璇戙
A good starting point is to copy the English .po file and to translate at least the technical messages, and maybe the validator messages, too.
浠ヨ嫳璇殑 .po 鏂囦欢涓哄熀纭锛岀炕璇戝叾涓殑鎶鏈浉鍏崇殑淇℃伅锛屽彲鑳借繕鍖呮嫭涓浜涗娇涔嬬敓鏁堢殑淇℃伅銆傝繖浼氭槸涓涓ソ鐨勫紑濮嬨
Technical message IDs are easily recognized; theyre all uppercase. You dont translate the message ID as with other messages; rather, you provide the correct local variant on the provided English value. For example, with DATETIME_FORMAT (or DATE_FORMAT or TIME_FORMAT ), this would be the format string that you want to use in your language. The format is identical to the format strings used by the now template tag.
鎶鏈浉鍏崇殑淇℃伅ID寰堝鏄撹浜哄嚭鏉ワ細瀹冧滑閮芥槸澶у啓鐨勩傝繖浜涗俊鎭疘D鐨勭炕璇戜笌鍏朵粬淇℃伅涓嶅悓:浣犻渶瑕佹彁渚涘叾瀵瑰簲鐨勬湰鍦板寲鍐呭銆備緥濡傦紝瀵逛簬 DATETIME_FORMAT 锛堟垨 DATE_FORMAT 銆 TIME_FORMAT 锛夛紝搴旇鎻愪緵甯屾湜鍦ㄨ璇█涓娇鐢ㄧ殑鏍煎紡鍖栧瓧绗︿覆銆傛牸寮忓拰 now 妯℃澘鏍囩涓娇鐢ㄧ殑鏍煎紡鍖栧瓧绗︿覆涓鏍枫
Once LocaleMiddleware determines the users preference, it makes this preference available as request.LANGUAGE_CODE for each request object. Feel free to read this value in your view code. Heres a simple example:
涓鏃 LocalMiddleware 纭畾浜嗙敤鎴风殑浣跨敤鍋忓ソ锛屽氨灏嗗叾浠 request.LANGUAGE_CODE 鐨勫舰寮忔彁渚涚粰姣忎釜璇锋眰瀵硅薄銆傚姝わ紝鍦ㄨ鍥句唬鐮佷腑灏卞彲浠ヨ嚜鐢变娇鐢ㄤ簡銆備互涓嬫槸涓涓畝鍗曠殑渚嬪瓙锛
def hello_world(request, count): if request.LANGUAGE_CODE == 'de-at': return HttpResponse("You prefer to read Austrian German.") else: return HttpResponse("You prefer to read another language.")
Note that, with static (i.e. without middleware) translation, the language is in settings.LANGUAGE_CODE , while with dynamic (middleware) translation, its in request.LANGUAGE_CODE .
娉ㄦ剰锛岄潤鎬佺炕璇戯紙鍗充笉缁忚繃涓棿浠讹級涓殑璇█璁剧疆鏄湪 settings.LANGUAGE_CODE 涓殑锛岃屽姩鎬佺炕璇戯紙鍗充娇鐢ㄤ簡涓棿浠讹級鐨勮瑷璁剧疆瀹炲湪 request.LANGUAGE_CODE 銆
As a convenience, Django comes with a view, django.views.i18n.set_language , that sets a users language preference and redirects back to the previous page.
鏂逛究璧疯锛孌jango鑷甫浜嗕竴涓 django.views.i18n.set_language 瑙嗗浘锛屼綔鐢ㄦ槸璁剧疆鐢ㄦ埛璇█鍋忓ソ骞堕噸瀹氬悜杩斿洖鍒板墠涓椤甸潰銆
Activate this view by adding the following line to your URLconf:
鍦║RLconf涓姞鍏ヤ笅闈㈣繖琛屼唬鐮佹潵婵娲昏繖涓鍥撅細
(r'^i18n/', include('django.conf.urls.i18n')),
(Note that this example makes the view available at /i18n/setlang/ .)
锛堟敞鎰忚繖涓緥瀛愪娇寰楄繖涓鍥惧湪 /i18n/setlang/ 涓湁鏁堛傦級
The view expects to be called via the GET method, with a language parameter set in the query string. If session support is enabled, the view saves the language choice in the users session. Otherwise, it saves the language choice in a django_language cookie.
杩欎釜瑙嗗浘鏄氳繃 GET 鏂规硶璋冪敤鐨勶紝鍦≦uery String涓寘鍚簡 language 鍙傛暟銆傚鏋渟ession宸插惎鐢紝杩欎釜瑙嗗浘浼氬皢璇█閫夋嫨淇濆瓨鍦ㄧ敤鎴风殑session涓傚惁鍒欙紝璇█閫夋嫨灏嗚淇濆瓨鍦ㄥ悕涓 django_language 鐨刢ookie涓
After setting the language choice, Django redirects the user, following this algorithm:
淇濆瓨浜嗚瑷閫夋嫨鍚庯紝Django鏍规嵁浠ヤ笅绠楁硶鏉ラ噸瀹氬悜椤甸潰锛
Django looks for a next parameter in the query string.
Django鍦ㄦ彁浜ょ殑Query String涓鎵 next 鍙傛暟銆
If that doesnt exist or is empty, Django tries the URL in the Referer header.
濡傛灉 next 鍙傛暟涓嶅瓨鍦ㄦ垨涓虹┖锛孌jango灏濊瘯閲嶅畾鍚戦〉闈负HTML澶撮儴淇℃伅涓 Referer 鐨勫笺
If thats empty say, if a users browser suppresses that header then the user will be redirected to / (the site root) as a fallback.
濡傛灉 Referer 涔熸槸绌虹殑锛屽嵆璇ョ敤鎴风殑娴忚鍣ㄥ苟涓嶅彂閫 Referer 澶翠俊鎭紝鍒欓〉闈㈠皢閲嶅畾鍚戝埌 / 锛堥〉闈㈡牴鐩綍锛夈
Heres example HTML template code:
杩欐槸涓涓狧TML妯℃澘浠g爜鐨勪緥瀛愶細
<form action="/i18n/setlang/" method="get"> <input name="next" type="hidden" value="/next/page/" /> <select name="language"> {% for lang in LANGUAGES %} <option value="{{ lang.0 }}">{{ lang.1 }}</option> {% endfor %} </select> <input type="submit" value="Go" /> </form>
Django looks for translations by following this algorithm:
Django浣跨敤浠ヤ笅绠楁硶瀵绘壘缈昏瘧锛
First, it looks for a locale directory in the application directory of the view thats being called. If it finds a translation for the selected language, the translation will be installed.
棣栧厛锛孌jango鍦ㄨ瑙嗗浘鎵鍦ㄧ殑搴旂敤绋嬪簭鏂囦欢澶逛腑瀵绘壘 locale 鐩綍銆傝嫢鎵惧埌鎵閫夎瑷鐨勭炕璇戯紝鍒欏姞杞借缈昏瘧銆
Next, it looks for a locale directory in the project directory. If it finds a translation, the translation will be installed.
绗簩姝ワ紝Django鍦ㄩ」鐩洰褰曚腑瀵绘壘 locale 鐩綍銆傝嫢鎵惧埌缈昏瘧锛屽垯鍔犺浇璇ョ炕璇戙
Finally, it checks the base translation in django/conf/locale .
鏈鍚庯紝Django浣跨敤 django/conf/locale 鐩綍涓殑鍩烘湰缈昏瘧銆
This way, you can write applications that include their own translations, and you can override base translations in your project path. Or, you can just build a big project out of several applications and put all translations into one big project message file. The choice is yours.
浠ヨ繖绉嶆柟寮忥紝浣犲彲浠ュ垱寤哄寘鍚嫭绔嬬炕璇戠殑搴旂敤绋嬪簭锛屽彲浠ヨ鐩栭」鐩腑鐨勫熀鏈炕璇戙傛垨鑰咃紝浣犲彲浠ュ垱寤轰竴涓寘鍚嚑涓簲鐢ㄧ▼搴忕殑澶ч」鐩紝骞跺皢鎵鏈夐渶瑕佺殑缈昏瘧鏀惧湪涓涓ぇ鐨勯」鐩俊鎭枃浠朵腑銆傚喅瀹氭潈鍦ㄤ綘鎵嬩腑銆
Note
娉ㄦ剰
If youre using manually configured settings, the locale directory in the project directory will not be examined, since Django loses the ability to work out the location of the project directory. (Django normally uses the location of the settings file to determine this, and a settings file doesnt exist if youre manually configuring your settings.)
濡傛灉鏄娇鐢ㄦ墜鍔ㄩ厤缃殑settings鏂囦欢锛屽洜Django鏃犳硶鑾峰彇椤圭洰鐩綍鐨勪綅缃紝鎵浠ラ」鐩洰褰曚笅鐨 locale 鐩綍灏嗕笉浼氳妫鏌ャ傦紙Django涓鑸娇鐢╯ettings鏂囦欢鐨勪綅缃潵纭畾椤圭洰鐩綍锛岃岃嫢鎵嬪姩閰嶇疆settings鏂囦欢锛屽垯settings鏂囦欢涓嶄細鍦ㄨ鐩綍涓傦級
All message file repositories are structured the same way:
鎵鏈夌殑淇℃伅鏂囦欢搴撻兘鏄互鍚屾牱鏂瑰紡缁勭粐鐨勶細
$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)
$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)
$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)
$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)
All paths listed in LOCALE_PATHS in your settings file are searched in that order for <language>/LC_MESSAGES/django.(po|mo)
鎵鏈夊湪settings鏂囦欢涓 LOCALE_PATHS 涓垪鍑虹殑璺緞浠ュ叾鍒楀嚭鐨勯『搴忔悳绱 <language>/LC_MESSAGES/django.(po|mo)
$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)
$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)
To create message files, you use the same make-messages.py tool as with the Django message files. You only need to be in the right place in the directory where either the conf/locale (in case of the source tree) or the locale/ (in case of application messages or project messages) directory is located. And you use the same compile-messages.py to produce the binary django.mo files that are used by gettext .
瑕佸垱寤轰俊鎭枃浠讹紝涔熸槸浣跨敤 make-messages.py 宸ュ叿锛屽拰Django淇℃伅鏂囦欢涓鏍枫傞渶瑕佸仛鐨勫氨鏄敼鍙樺埌姝g‘鐨勭洰褰曚笅鈥斺 conf/locale 锛堝湪婧愮爜鏍戠殑鎯呭喌涓嬶級鎴栬 locale/ 锛堝湪搴旂敤绋嬪簭淇℃伅鎴栭」鐩俊鎭殑鎯呭喌涓嬶級鎵鍦ㄧ殑鐩綍涓嬨傚悓鏍峰湴锛屼娇鐢 compile-messages.py 鐢熸垚 gettext 闇瑕佷娇鐢ㄧ殑浜岃繘鍒 django.mo 鏂囦欢銆
Application message files are a bit complicated to discover they need the LocaleMiddleware . If you dont use the middleware, only the Django message files and project message files will be processed.
搴旂敤绋嬪簭淇℃伅鏂囦欢绋嶅井闅句互鍙戠幇鈥斺斿洜涓哄畠浠渶瑕 LocaleMiddle 銆傚鏋滀笉浣跨敤涓棿浠讹紝Django鍙細澶勭悊Django鐨勪俊鎭枃浠跺拰椤圭洰鐨勪俊鎭枃浠躲
Finally, you should give some thought to the structure of your translation files. If your applications need to be delivered to other users and will be used in other projects, you might want to use application-specific translations. But using application-specific translations and project translations could produce weird problems with make-messages . make-messages will traverse all directories below the current path and so might put message IDs into the project message file that are already in application message files.
鏈鍚庯紝闇瑕佽冭檻涓涓嬬炕璇戞枃浠剁殑缁撴瀯銆傝嫢搴旂敤绋嬪簭瑕佸彂鏀剧粰鍏朵粬鐢ㄦ埛锛屽簲鐢ㄥ埌鍏跺畠椤圭洰涓紝鍙兘闇瑕佷娇鐢ㄥ簲鐢ㄧ▼搴忕浉鍏崇殑缈昏瘧銆備絾鏄紝浣跨敤搴旂敤绋嬪簭鐩稿叧鐨勭炕璇戝拰椤圭洰缈昏瘧鍦ㄤ娇鐢 make-messages 鏃朵細浜х敓鍙ゆ殑闂銆 make-messages 浼氶亶鍘嗗綋鍓嶈矾寰勪笅鐨勬墍鏈夌洰褰曪紝鎵浠ュ彲鑳戒細灏嗗簲鐢ㄧ▼搴忎俊鎭枃浠跺凡鏈夌殑淇℃伅ID鏀惧湪椤圭洰淇℃伅鏂囦欢涓
The easiest way out is to store applications that are not part of the project (and so carry their own translations) outside the project tree. That way, make-messages on the project level will only translate strings that are connected to your explicit project and not strings that are distributed independently.
鏈瀹规槗鐨勮В鍐虫柟娉曞氨鏄皢涓嶅睘浜庨」鐩殑搴旂敤绋嬪簭锛堝洜姝ら檮甯︾潃鏈韩鐨勭炕璇戯級瀛樺偍鍦ㄩ」鐩爲涔嬪銆傝繖鏍峰仛鐨勮瘽锛岄」鐩骇鐨 make-messages 灏嗗彧浼氱炕璇戜笌椤圭洰绮剧‘鐩稿叧鐨勶紝鑰屼笉鍖呮嫭閭d簺鐙珛鍙戝竷鐨勫簲鐢ㄧ▼搴忎腑鐨勫瓧绗︿覆銆
缈昏瘧涓嶫avaScript
Adding translations to JavaScript poses some problems:
灏嗙炕璇戞坊鍔犲埌JavaScript浼氬紩璧蜂竴浜涢棶棰橈細
JavaScript code doesnt have access to a gettext implementation.
JavaScript浠g爜鏃犳硶璁块棶涓涓 gettext 鐨勫疄鐜般
JavaScript code doesnt have access to .po or .mo files; they need to be delivered by the server.
JavaScript浠g爜鏃犳硶璁块棶 .po 鎴 .mo 鏂囦欢锛屽畠浠渶瑕佺敱鏈嶅姟鍣ㄥ垎鍙戙
The translation catalogs for JavaScript should be kept as small as possible.
閽堝JavaScript鐨勭炕璇戠洰褰曞簲灏介噺灏忋
Django provides an integrated solution for these problems: it passes the translations into JavaScript, so you can call gettext and friends from within JavaScript.
Django宸茬粡鎻愪緵浜嗕竴涓泦鎴愯В鍐虫柟妗堬細瀹冧細灏嗙炕璇戜紶閫掔粰JavaScript锛屽洜姝ゅ氨鍙互鍦↗avaScript涓皟鐢 gettext 涔嬬被鐨勪唬鐮併
The main solution to these problems is the javascript_catalog view, which generates a JavaScript code library with functions that mimic the gettext interface, plus an array of translation strings. Those translation strings are taken from the application, project, or Django core, according to what you specify in either the info_dict or the URL.
杩欎簺闂鐨勪富瑕佽В鍐虫柟妗堝氨鏄 javascript_catalog 瑙嗗浘銆傝瑙嗗浘鐢熸垚涓涓狫avaScript浠g爜搴擄紝鍖呮嫭妯′豢 gettext 鎺ュ彛鐨勫嚱鏁帮紝鍜岀炕璇戝瓧绗︿覆鐨勬暟缁勩傝繖浜涚炕璇戝瓧绗︿覆鏉ヨ嚜搴旂敤绋嬪簭锛岄」鐩紝鎴栬匘jango鏍稿績锛屽叿浣撶敱 info_dict 鎴朥RL鏉ョ‘瀹氥
You hook it up like this:
鍍忚繖鏍蜂娇鐢細
js_info_dict = { 'packages': ('your.app.package',), } urlpatterns = patterns('', (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict), )
Each string in packages should be in Python dotted-package syntax (the same format as the strings in INSTALLED_APPS ) and should refer to a package that contains a locale directory. If you specify multiple packages, all those catalogs are merged into one catalog. This is useful if youre depending upon JavaScript that uses strings from different applications.
packages 閲岀殑姣忎釜瀛楃涓插簲璇ユ槸Python涓殑鐐瑰垎鍓茬殑鍖呯殑琛ㄨ揪寮忓舰寮忥紙鍜屽湪 INSTALLED_APPS 涓殑瀛楃涓茬浉鍚岀殑鏍煎紡锛夛紝鑰屼笖搴旀寚鍚戝寘鍚 locale 鐩綍鐨勫寘銆傚鏋滄寚瀹氫簡澶氫釜鍖咃紝鎵鏈夌殑鐩綍浼氬悎骞舵垚涓涓洰褰曘傚鏋滄湁鐢ㄥ埌鏉ヨ嚜涓嶅悓搴旂敤绋嬪簭鐨勫瓧绗︿覆鐨凧avaScript锛岃繖绉嶆満鍒朵細寰堟湁甯姪銆
You can make the view dynamic by putting the packages into the URL pattern:
浣犲彲浠ュ姩鎬佷娇鐢ㄨ鍥撅紝灏嗗寘鏀惧湪urlpatterns閲岋細
urlpatterns = patterns('', (r'^jsi18n/(?P<packages>\S+?)/$, 'django.views.i18n.javascript_catalog'), )
With this, you specify the packages as a list of package names delimited by plus signs (+ ) in the URL. This is especially useful if your pages use code from different applications, and this changes often and you dont want to pull in one big catalog file. As a security measure, these values can only be either django.conf or any package from the INSTALLED_APPS setting.
杩欐牱鐨勮瘽锛屽氨鍙互鍦║RL涓寚瀹氱敱鍔犲彿锛 + 锛夊垎闅斿寘鍚嶇殑鍖呬簡銆傚鏋滈〉闈娇鐢ㄦ潵鑷笉鍚屽簲鐢ㄧ▼搴忕殑浠g爜锛屼笖缁忓父鏀瑰彉锛岃繕涓嶆兂灏嗗叾鏀惧湪涓涓ぇ鐨勭洰褰曟枃浠朵腑锛屽浜庤繖浜涙儏鍐碉紝鏄剧劧杩欐槸寰堟湁鐢ㄧ殑銆傚嚭浜庡畨鍏ㄨ冭檻锛岃繖浜涘煎彧鑳芥槸 django.conf 鎴 INSTALLED_APPS 璁剧疆涓殑鍖呫
To use the catalog, just pull in the dynamically generated script like this:
瑕佷娇鐢ㄨ繖涓洰褰曪紝鍙杩欐牱寮曞叆鍔ㄦ佺敓鎴愮殑鑴氭湰锛
<script type="text/javascript" src="/path/to/jsi18n/"></script>
This is how the admin site fetches the translation catalog from the server. When the catalog is loaded, your JavaScript code can use the standard gettext interface to access it:
杩欏氨鏄鐞嗛〉闈㈠浣曚粠鏈嶅姟鍣ㄨ幏鍙栫炕璇戠洰褰曘傚綋鐩綍鍔犺浇鍚庯紝JavaScript浠g爜灏辫兘閫氳繃鏍囧噯鐨 gettext 鎺ュ彛杩涜璁块棶锛
document.write(gettext('this is to be translated'));
There even is a ngettext interface and a string interpolation function:
鐢氳嚦鏈変竴涓 ngettext 鎺ュ彛鍜屼竴涓瓧绗︿覆鏌ヨˉ鍑芥暟锛
d = { count: 10 }; s = interpolate(ngettext('this is %(count)s object', 'this are %(count)s objects', d.count), d);
The interpolate function supports both positional interpolation and named interpolation. So the preceding code could have been written as follows:
interpolate 鍑芥暟鏀寔浣嶇疆鎻掕ˉ鍜屽悕瀛楁煡琛ャ傚洜姝ゅ墠闈㈢殑浠g爜涔熷彲浠ュ啓鎴愯繖鏍凤細
s = interpolate(ngettext('this is %s object', 'this are %s objects', 11), [11]);
The interpolation syntax is borrowed from Python. You shouldnt go over the top with string interpolation, though this is still JavaScript, so the code will have to do repeated regular-expression substitutions. This isnt as fast as string interpolation in Python, so keep it to those cases where you really need it (e.g., in conjunction with ngettext to produce proper pluralization).
鎻掕ˉ鐨勮娉曟槸鍊熼壌浜哖ython銆備絾涓嶅簲璇ヨ秴杩囧瓧绗︿覆鎻掕ˉ鐨勮兘鍔涳紝杩欎粛鐒惰繕鏄疛avaScript锛屽洜姝や唬鐮佸皢涓嶅緱涓嶅仛閲嶅鐨勬鍒欐浛鎹€傚畠涓嶄細鍜孭ython涓殑瀛楃涓叉彃琛ヤ竴鏍峰揩锛屽洜姝ゅ彧鏈夌湡姝i渶瑕佺殑鏃跺欏啀浣跨敤瀹冿紙渚嬪锛屽埄鐢 ngettext 鐢熸垚鍚堥傜殑澶嶆暟褰㈠紡锛夈
You create and update the translation catalogs the same way as the other Django translation catalogs: with the `make-messages.py` tool. The only difference is you need to provide a -d djangojs parameter, like this:
鐢ㄥ拰鍏跺畠Django缈昏瘧鐩綍鐩稿悓鐨勬柟娉曟潵鍒涘缓鍜屾洿鏂癑avaScript缈昏瘧鐩綍锛氱敤 `make-messages.py` 宸ュ叿銆傚敮涓鐨勫樊鍒槸闇瑕佹彁渚涗竴涓 -d djangojs 鐨勫弬鏁帮紝灏卞儚杩欐牱锛
make-messages.py -d djangojs -l de
This creates or updates the translation catalog for JavaScript for German. After updating translation catalogs, just run compile-messages.py the same way as you do with normal Django translation catalogs.
杩欐牱鏉ュ垱寤烘垨鏇存柊JavaScript鐨勫痉璇炕璇戠洰褰曘傚拰鏅氱殑Django缈昏瘧鐩綍涓鏍凤紝鏇存柊浜嗙炕璇戠洰褰曞悗锛岃繍琛 compile-messages.py 鍗冲彲銆
If you know gettext , you might note these special things in the way Django does translation:
濡傛灉浣犱簡瑙 gettext 锛屼綘鍙兘浼氬彂鐜癉jango杩涜缈昏瘧鏃剁殑涓浜涚壒娈婄殑涓滆タ锛
The string domain is django or djangojs . The string domain is used to differentiate between different programs that store their data in a common message-file library (usually /usr/share/locale/ ). The django domain is used for Python and template translation strings, and is loaded into the global translation catalogs. The djangojs domain is only used for JavaScript translation catalogs to make sure that those are as small as possible.
瀛楃涓插煙涓 django 鎴 djangojs 銆傚瓧绗︿覆鍩熸槸鐢ㄦ潵鍖哄埆灏嗘暟鎹瓨鍌ㄥ湪鍚屼竴淇℃伅鏂囦欢搴擄紙涓鑸槸 /usr/share/locale/ 锛夌殑涓嶅悓绋嬪簭銆 django 鍩熸槸涓篜ython鍜屾ā鏉跨炕璇戝瓧绗︿覆鏈嶅姟鐨勶紝琚姞杞藉埌鍏ㄥ眬缈昏瘧鐩綍銆 djangojs 鍩熺敤鍦↗avaScript缈昏瘧鐩綍涓紝浠ョ‘淇濆叾瓒冲灏忋
Django only uses gettext and gettext_noop . Thats because Django always uses DEFAULT_CHARSET strings internally. There isnt much benefit to using ugettext , because youll always need to produce UTF-8 anyway.
Django浠呴傜敤 gettext 鍜 gettext_noop 銆傝繖鏄洜涓篋jango鎬绘槸鍐呭湪鍦颁娇鐢 DEFAULT_CHARSET 瀛楃涓层備娇鐢 ugettext 骞舵病鏈変粈涔堝ソ澶勶紝鍥犱负鎬绘槸闇瑕佺敓鎴怳TF-8銆
Django doesnt use xgettext alone. It uses Python wrappers around xgettext and msgfmt . Thats mostly for convenience.
Django涓嶅崟鐙娇鐢 xgettext 锛岃屾槸缁忚繃Python鍖呰鍚庣殑 xgettext 鍜 msgfmt 銆傝繖涓昏鏄负浜嗘柟渚裤
This chapter mostly concludes our coverage of Djangos features. You should now know enough to start producing your own Django sites.
杩欎竴绔犲熀鏈笂宸茬粡缁撴潫浜嗘垜浠浜嶥jango鐗规х殑浠嬬粛銆備綘搴旇宸茬粡鎺屾彙浜嗗垱寤轰綘鑷繁Django椤甸潰鐨勭煡璇嗐
However, writing the code is only the first step in deploying a successful Web site. The next two chapters cover the things youll need to know if you want your site to survive in the real world. Chapter 19 discuses how you can secure your sites and your users from malicious attackers, and Chapter 20 details how to deploy a Django application onto one or many servers.
鐒惰岋紝缂栫爜宸ヤ綔浠呬粎鏄儴缃蹭竴涓垚鍔熺綉绔欑殑绗竴姝ャ傛帴涓嬫潵鐨勪袱绔犲寘鎷簡浣犵殑缃戠珯鍦ㄧ綉缁滀笘鐣岀殑鐢熷瓨涔嬮亾銆傜19绔犺璁轰簡濡備綍闃茶寖鎭舵剰鏀诲嚮锛屼互澧炲己绔欑偣鐨勫畨鍏ㄦэ紝淇濇姢浣跨敤鑰呯殑瀹夊叏锛涚20绔犺杩颁簡濡備綍灏嗕竴涓狣jango搴旂敤绋嬪簭閮ㄧ讲鍒颁竴涓垨澶氫釜鏈嶅姟鍣ㄤ笂銆
鍏充簬鏈瘎娉ㄧ郴缁
鏈珯浣跨敤涓婁笅鏂囧叧鑱旂殑璇勬敞绯荤粺鏉ユ敹闆嗗弽棣堜俊鎭備笉鍚屼簬涓鑸鏁寸珷鍋氳瘎娉ㄧ殑鍋氭硶锛 鎴戜滑鍏佽浣犲姣忎竴涓嫭绔嬬殑鈥滄枃鏈潡鈥濆仛璇勬敞銆備竴涓滄枃鏈潡鈥濈湅璧锋潵鏄繖鏍风殑锛
涓涓滄枃鏈潡鈥濇槸涓涓钀斤紝涓涓垪琛ㄩ」锛屼竴娈典唬鐮侊紝鎴栬呭叾浠栦竴灏忔鍐呭銆 浣犻変腑瀹冧細楂樹寒搴︽樉绀:
瑕佸鏂囨湰鍧楀仛璇勬敞锛屼綘鍙渶瑕佺偣鍑诲畠鏃佽竟鐨勬爣璇嗗潡:
鎴戜滑浼氫粩缁嗛槄璇绘瘡涓瘎璁猴紝濡傛灉鍙兘鐨勮瘽鎴戜滑涔熶細鎶婅瘎娉ㄨ冭檻鍒版湭鏉ョ殑鐗堟湰涓幓:
濡傛灉浣犳効鎰忎綘鐨勮瘎娉ㄨ閲囩敤锛岃纭繚鐣欎笅浣犵殑鍏ㄥ悕 (娉ㄦ剰涓嶆槸鏄电О鎴栫畝绉帮級
Many, many thanks to Jack Slocum; the inspiration and much of the code for the comment system comes from Jack's blog, and this site couldn't have been built without his wonderful
YAHOO.ext
library. Thanks also to Yahoo for YUI itself.