深入學習Django源碼基礎8 - Django中系統級國際化本地化

具體使用步驟與分析http://www.ibm.com/developerworks/cn/web/1101_jinjh_djangoi18n/


本篇主要分析系統級的方法。不涉及自定義的

代碼太多,採用逆向部分源碼法來學習分析

main.py源碼

import os
from django.utils.formats import *

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.settings')
print get_format('DATETIME_INPUT_FORMATS')


時間部分

ISO_INPUT_FORMATS = {
    'DATE_INPUT_FORMATS': ('%Y-%m-%d',),
    'TIME_INPUT_FORMATS': ('%H:%M:%S', '%H:%M'),
    'DATETIME_INPUT_FORMATS': (
        '%Y-%m-%d %H:%M:%S',
        '%Y-%m-%d %H:%M:%S.%f',
        '%Y-%m-%d %H:%M',
        '%Y-%m-%d'
    ),
}


settings.py中

__author__ = 'watsy'

TIME_ZONE = 'Asia/Shanghai'
LANGUAGE_CODE = 'en-us'
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGE_CODE = 'zh-cn'
SECRET_KEY = 'm&vr890n*%65ed4!alhj!-d=24cz+#)0%5@dq_8bgc&0p'

進入get_format中,查看文件提供方法

_format_cache
_format_modules_cache
ISO_INPUT_FORMATS
reset_format_cache()
iter_format_modules()
iter_format_modules(lang)
get_format_modules(lange=None,reverse=False)
get_format(format_type,lang=None,use_l10n=None)
get_format_lazy
date_format(value,format=None,use_l10n=None)
time_format(value,format=None,use_l10n=None)
....
localize(value,use_l10n=None)
...

下面的全部調用到get_format獲取。因此進入get_format函數

def get_format(format_type, lang=None, use_l10n=None):
    format_type = force_str(format_type)
    if use_l10n or (use_l10n is None and settings.USE_L10N):
        if lang is None:
            lang = get_language()
        cache_key = (format_type, lang)
        try:
            cached = _format_cache[cache_key]
            if cached is not None:
                return cached
            else:
                # Return the general setting by default
                return getattr(settings, format_type)
        except KeyError:
            for module in get_format_modules(lang):
                try:
                    val = getattr(module, format_type)
                    for iso_input in ISO_INPUT_FORMATS.get(format_type, ()):
                        if iso_input not in val:
                            if isinstance(val, tuple):
                                val = list(val)
                            val.append(iso_input)
                    _format_cache[cache_key] = val
                    return val
                except AttributeError:
                    pass
            _format_cache[cache_key] = None
    return getattr(settings, format_type)
首先判斷是否支持國際化

  如果支持,並且提供語言

     獲取語言
  生存緩存關鍵字

       獲取緩存並返回

       異常以後加載國際化語言模塊從新獲取,並記錄到緩存


因此重點分析獲取語言模塊提取部分

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

def get_format_modules(lang=None, reverse=False):
    """
    Returns a list of the format modules found
    """
    if lang is None:
        lang = get_language()
    modules = _format_modules_cache.setdefault(lang, list(iter_format_modules(lang)))
    if reverse:
        return list(reversed(modules))
    return modules

獲取格式化模塊部分重點在list遍歷生成部分

def iter_format_modules(lang):
    """
    Does the heavy lifting of finding format modules.
    """
    if check_for_language(lang):
        format_locations = ['django.conf.locale.%s']
        if settings.FORMAT_MODULE_PATH:
            format_locations.append(settings.FORMAT_MODULE_PATH + '.%s')
            format_locations.reverse()
        locale = to_locale(lang)
        locales = [locale]
        if '_' in locale:
            locales.append(locale.split('_')[0])
        for location in format_locations:
            for loc in locales:
                try:
                    yield import_module('.formats', location % loc)
                except ImportError:
                    pass

檢查語言是否支持

   格式化語言模塊

   加載

def import_module(name, package=None):
    if name.startswith('.'):
        if not package:
            raise TypeError("relative imports require the 'package' argument")
        level = 0
        for character in name:
            if character != '.':
                break
            level += 1
        name = _resolve_name(name[level:], package, level)
    __import__(name)
    return sys.modules[name]

分析檢查是否支持語言模塊,最終定位到utils中translation下trans_real.py文件中

def check_for_language(lang_code):
    for path in all_locale_paths():
        if gettext_module.find('django', path, [to_locale(lang_code)]) is not None:
            return True
    return False

遍歷本地化路徑,判斷多國語言的編碼模塊是否支持

進入本地化路徑部分

def all_locale_paths():
    from django.conf import settings
    globalpath = os.path.join(
        os.path.dirname(upath(sys.modules[settings.__module__].__file__)), 'locale')
    return [globalpath] + list(settings.LOCALE_PATHS)

這段代碼比較有意思,文件加載部分。

全局的代碼會得到django.core.locale路徑

本地化路徑需要在settings.LOCALE_PATHS變量中設置。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------


獲取語言部分

def get_language():
    t = getattr(_active, "value", None)
    if t is not None:
        try:
            return t.to_language()
        except AttributeError:
            pass
    from django.conf import settings
    return settings.LANGUAGE_CODE

得到當前激活的語言,否則返回settings.LANGUAGE_CODE語言


在來看本地化語言的路徑。


這裏與上一片本地化內容一樣了。


其他函數經過分析可以看出來

trans_real.py 包裝了python的本地化方法。針對http部分進行了增強

format.py文件提供格式化系統級別的一些多國語言函數


以後有時間在分析app內使用的原理~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章