實施操作
控制節點
sudo -i
#進入horizon服務的容器
lxc-attach -n infra1_horizon_container-314417a3
#在用戶根目錄創建目錄zunui-i18n
mkdir ~/zunui-i18n
# 進入目錄
cd ~/zunui-i18n
#將要替換的文件發送到這個目錄下
rz
# 備份
cp /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po.bak
cp /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/djangojs.po /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/djangojs.po.bak
cp /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/dashboard/container/containers/details/console.controller.js /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/dashboard/container/containers/details/console.controller.js.bak
cp /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/cloud-shell/cloud-shell.controller.js /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/cloud-shell/cloud-shell.controller.js.bak
# 拷貝文件並修改權限和所有者
cp ~/zunui-i18n/django.po /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/
chown root:root /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po
chmod 644 /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po
cp ~/zunui-i18n/djangojs.po /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/
chown root:root /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/djangojs.po
chmod 644 /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/djangojs.po
cp ~/zunui-i18n/console.controller.js /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/dashboard/container/containers/details/
chown root:root /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/dashboard/container/containers/details/console.controller.js
chmod 644 /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/dashboard/container/containers/details/console.controller.js
cp ~/zunui-i18n/cloud-shell.controller.js /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/cloud-shell/
chown root:root /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/cloud-shell/cloud-shell.controller.js
chmod 644 /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/static/cloud-shell/cloud-shell.controller.js
# 翻譯po
msgfmt --statistics --verbose -o /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.mo /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/django.po
msgfmt --statistics --verbose -o /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/djangojs.mo /openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/djangojs.po
# 發佈靜態文件
/openstack/venvs/horizon-18.1.5/bin/horizon-manage.py collectstatic --noinput
/openstack/venvs/horizon-18.1.5/bin/horizon-manage.py compress --force
# 重啓並查看Apache服務
systemctl restart apache2
systemctl status apache2
(以上腳本被保存在文件i18n-zunui.sh中。)
說明
以替換文件方式進行,文件包括:
# 自己寫的腳本
i18n-zunui.sh
# js的國際化文件
djangojs.po
# py的國際化文件
django.po
# 容器詳情中,console標籤頁的controller文件
console.controller.js
# cloud-shell的controller文件,未使用,找到就一起改了。。。
cloud-shell.controller.js
覆蓋的文件都修改了哪些內容?
-
django.po
py文件中要漢化的部分,主要是面板和麪板組的漢化。
主要是在末尾添加了要漢化的內容。 -
djangojs.po
zun-ui的大部分頁面都是使用angularjs寫的,所以大部分列表中的文字都是在js/html中進行的國際化。
主要是在末尾添加了要漢化的內容。 -
console.controller.js
修改方法onGetContainer(response),對生成的dom元素中的文字進行國際化
function onGetContainer(container) {
//rwz add
var enableInteractiveModeTipStr = gettext("To display console," +
"interactive mode needs to be enabled when this container was created.");
var notRunningStr = gettext("Container is not running.");
ctrl.container = container.data;
var consoleUrl = webRoot + "containers/" + ctrl.container.id + "/console";
//var console = $("<p>To display console, interactive mode needs to be enabled " +
// "when this container was created.</p>");
var console = $("<p>" + enableInteractiveModeTipStr + "</p>");
if (ctrl.container.status !== "Running") {
//console = $("<p>Container is not running.</p>");
console = $("<p>"+ notRunningStr +"</p>");
} else if (ctrl.container.interactive) {
console = $("<iframe id=\"console_embed\" src=\"" + consoleUrl +
"\" style=\"width:100%;height:100%\"></iframe>");
}
$("#console").append(console);
}
- cloud-shell.controller.js
修改方法onGetContainer(response),對生成的dom元素中的文字進行國際化
function onGetContainer(response) {
ctrl.container = response.data;
//rwz add
var enableInteractiveModeTipStr = gettext("To display console," +
"interactive mode needs to be enabled when this container was created.");
var notRunningStr = gettext("Container is not running.Please wait for starting up container.");
// attach console to existing container
ctrl.consoleUrl = webRoot + "containers/" + ctrl.container.id + "/console";
//var console = $("<p>To display console, interactive mode needs to be enabled " +
// "when this container was created.</p>");
var console = $("<p>" + enableInteractiveModeTipStr + "</p>");
if (ctrl.container.status !== "Running") {
//console = $("<p>Container is not running. Please wait for starting up container.</p>");
console = $("<p>" + notRunningStr + "</p>");
} else if (ctrl.container.interactive) {
console = $("<iframe id=\"console_embed\" src=\"" + ctrl.consoleUrl +
"\" style=\"width:100%;height:100%\"></iframe>");
// execute openrc.sh on the container
var command = "sh -c 'printf \"" + cloudsYaml + "\" > ~/.config/openstack/clouds.yaml'";
zun.executeContainer(ctrl.container.id, {command: command}).then(function() {
var command = "sh -c 'printf \"export OS_CLOUD=openstack\" > ~/.bashrc'";
zun.executeContainer(ctrl.container.id, {command: command}).then(function() {
angular.noop();
});
});
}
// append shell content
angular.element("#shell-content").append(console);
}
文件存放路徑
po文件位置:
/openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/openstack_dashboard/locale/zh_CN/LC_MESSAGES/
zun-ui目錄位置:
/openstack/venvs/horizon-18.1.5/lib/python2.7/site-packages/zun_ui/
國際化的主要思路
查找源文件中涉及國際化的部分:
py、js文件中調用gettext()方法,html使用translate標記的的部分,結合出現位置上下文進行翻譯。
其中,js文件和html文件的翻譯要放到djangojs.po文件中,py文件的翻譯要放到django.po文件中。
對於沒有使用國際化方法,直接在頁面中顯示英文的情況,根據需要決定是否修改代碼,以支持國際化。
遇到的一些問題
一詞多義
使用msgctxt標記,添加上下文信息。
相應的,gettext方法要換爲ngettext方法。(未驗證)
po文件寫法 :
msgctxt "month name"
msgid "May"
msgstr ""
template寫法:
{% trans "May" context "month name" %}
源碼中未考慮國際化
對於直接輸出到頁面的,如:
zun_ui/static/dashboard/container/containers/details/console.controller.js
zun_ui/static/cloud-shell/cloud-shell.controller.js
需要適當修改代碼,調用gettext方法,已實現國際化。
對於從api中獲去數據的,如:
zun_ui/static/dashboard/container/containers/containers.module.js
需要增加filter來處理國際化的信息。
//angular.module**** 的最後追加
.filter('translatetext', getTranslateText)
//containerProperties()方法中,對於未被正確翻譯的字段,如status,添加filter
'status': {label: gettext('Status'), filters: ['noValue', 'translatetext'] },
function getTranslateText() {
return function(input){
return gettext(input);
}
}
這裏,可以根據具體需要,添加合適的國際化/過濾操作。
html中的多行內容
形如:
<p translate>
When the <b>Admin State</b> for a network is set to <b>Up</b>,
then the network is available for use. You can set the <b>Admin State</b> to <b>Down</b>
if you are not ready for other users to access the network.
</p>
在翻譯時,msgid中的內容要保留html中的格式,包括空格,換行,首尾可以不管。
msgid ""
"When the <b>Admin State</b> for a network is set to <b>Up</b>,\n"
" then the network is available for use. You can set the <b>Admin State</"
"b> to <b>Down</b>\n"
" if you are not ready for other users to access the network."
msgstr ""
"當網絡的<b>管理狀態</b>被設置爲<b>正常</b>,\n"
"網絡將會是可用的。如果您還沒有準備讓別人訪問該網絡,\n"
"可以把<b>管理狀態</b>設置爲<b>停止</b>。"