﻿<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
	<id>https://wiki.blender.jp/index.php?action=history&amp;feed=atom&amp;title=%E5%88%A9%E7%94%A8%E8%80%85%3AXiaoxiangquan%2FGoogleSummerOfCode%2F2011%2FInternationalization%2Fdesign</id>
	<title>利用者:Xiaoxiangquan/GoogleSummerOfCode/2011/Internationalization/design - 版の履歴</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.blender.jp/index.php?action=history&amp;feed=atom&amp;title=%E5%88%A9%E7%94%A8%E8%80%85%3AXiaoxiangquan%2FGoogleSummerOfCode%2F2011%2FInternationalization%2Fdesign"/>
	<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=%E5%88%A9%E7%94%A8%E8%80%85:Xiaoxiangquan/GoogleSummerOfCode/2011/Internationalization/design&amp;action=history"/>
	<updated>2026-04-21T17:31:33Z</updated>
	<subtitle>このウィキのこのページに関する変更履歴</subtitle>
	<generator>MediaWiki 1.31.0</generator>
	<entry>
		<id>https://wiki.blender.jp/index.php?title=%E5%88%A9%E7%94%A8%E8%80%85:Xiaoxiangquan/GoogleSummerOfCode/2011/Internationalization/design&amp;diff=106703&amp;oldid=prev</id>
		<title>Yamyam: 1版 をインポートしました</title>
		<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=%E5%88%A9%E7%94%A8%E8%80%85:Xiaoxiangquan/GoogleSummerOfCode/2011/Internationalization/design&amp;diff=106703&amp;oldid=prev"/>
		<updated>2018-06-28T19:45:55Z</updated>

		<summary type="html">&lt;p&gt;1版 をインポートしました&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ja&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← 古い版&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;2018年6月28日 (木) 19:45時点における版&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;ja&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(相違点なし)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Yamyam</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.blender.jp/index.php?title=%E5%88%A9%E7%94%A8%E8%80%85:Xiaoxiangquan/GoogleSummerOfCode/2011/Internationalization/design&amp;diff=106702&amp;oldid=prev</id>
		<title>wiki&gt;Xiaoxiangquan: /* Font Loading */</title>
		<link rel="alternate" type="text/html" href="https://wiki.blender.jp/index.php?title=%E5%88%A9%E7%94%A8%E8%80%85:Xiaoxiangquan/GoogleSummerOfCode/2011/Internationalization/design&amp;diff=106702&amp;oldid=prev"/>
		<updated>2011-08-22T15:46:37Z</updated>

		<summary type="html">&lt;p&gt;‎&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Font Loading&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新規ページ&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{Page/Header|&amp;lt;blender version&amp;gt;|&amp;lt;previous page&amp;gt;|&amp;lt;next page&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
=Garlic's Internationalization Design=&lt;br /&gt;
&lt;br /&gt;
We use [http://www.gnu.org/software/gettext GNU Gettext] to translate strings. Here is the standard workflow.&lt;br /&gt;
&lt;br /&gt;
==GNU Gettext Workflow==&lt;br /&gt;
- Firstly, a programmer writes a piece of code containing strings that he wants them to be translated into end users' local language. The original code is like:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
ot-&amp;gt;name = &amp;quot;Quit&amp;quot;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To use GNU Gettext, the programmer wrote like this:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* header for gettext */&lt;br /&gt;
#include &amp;lt;libintl.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
ot-&amp;gt;name = gettext(&amp;quot;Quit&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- Then the programmer ran the command xgettext, which will scan the source files specified, and gather the words in gettext(&amp;quot;&amp;quot;). Finally, xgettext will gennerate a .pot file, whose suffix means a PO Template.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- A po is a translation file with items like:&lt;br /&gt;
  msgid &amp;quot;Wave&amp;quot;&lt;br /&gt;
  msgstr &amp;quot;Vague&amp;quot;&lt;br /&gt;
Actually, this is a po for French, generally named fr.po. Translators use msgmerge command to merge the old PO and the newly updated POT, then all the new changes will be available to see in the PO. If there is no &amp;quot;Quit&amp;quot; item in the old PO, now there will be:&lt;br /&gt;
  msgid &amp;quot;Quit&amp;quot;&lt;br /&gt;
  msgstr &amp;quot;&amp;quot;&lt;br /&gt;
Then translators can open the PO and fill untranslated strings.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- After the PO is translated, anyone can execute a msgfmt command to compile it as a MO file, and replace the old one used by the application. And the repository maintainer could update the MO to the trunk, too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
- At runtime, the gettext(&amp;quot;Quit&amp;quot;) calling will find the &amp;quot;Quit&amp;quot; entry in the MO and replace the string with the mapped one. Finally, users see a localized message if he has set application's locale and language properly.&lt;br /&gt;
&lt;br /&gt;
  Note that If there is no target entry or just an empty one,&lt;br /&gt;
  the calling will return the original message. &lt;br /&gt;
&lt;br /&gt;
Now as you can see, this work has great need for cooperations.&lt;br /&gt;
&lt;br /&gt;
==More about Gathering and Translating==&lt;br /&gt;
&lt;br /&gt;
In the process above, the gettext(str) act as two roles: mark the string to be gathered by xgettext command, and do the real translate at runtime. Actually, we can seperate these two stages as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define Mark(msgid) msgid&lt;br /&gt;
#define Trans(msgid) gettext(msgid)&lt;br /&gt;
...&lt;br /&gt;
ot-&amp;gt;name = Mark(&amp;quot;Quit&amp;quot;);&lt;br /&gt;
ot-&amp;gt;name = Trans(ot-&amp;gt;name);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this style, the Mark() do nothing. But if we add &amp;quot;Mark&amp;quot; as a keyword for xgettext, the command will notice that &amp;quot;Quit&amp;quot; should be gathered. And at runtime, the Trans() calling will do the real thanstation.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that the xgettext is not intelligent enough to notice the &amp;quot;Quit&amp;quot; through Trans() calling, as the ot-&amp;gt;name is not an evident string. Even the following syntax will not pass:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define SubStr &amp;quot;DEF&amp;quot;&lt;br /&gt;
...&lt;br /&gt;
/* cannot recognize string constants concatenated with macro */&lt;br /&gt;
ot-&amp;gt;name = gettext(&amp;quot;ABC&amp;quot; SubStr &amp;quot;GHI&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While simple string constants concat could be handled well:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* xgettext works well to gather &amp;quot;ABCDEFGHI&amp;quot; */&lt;br /&gt;
ot-&amp;gt;name = gettext(&amp;quot;ABC&amp;quot; &amp;quot;DEF&amp;quot; &amp;quot;GHI&amp;quot;);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Further more, format string can be handled well only if the translated string contains the same number and type of format elements, or else a runtime error may occur:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* make sure the translated &amp;quot;Hello, %s!&amp;quot; contains &amp;quot;%s&amp;quot; */&lt;br /&gt;
printf( gettext(&amp;quot;Hello, %s!&amp;quot;), gettext(&amp;quot;world&amp;quot;) ); &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Garlic's Gettext Framework==&lt;br /&gt;
===Supporting Files===&lt;br /&gt;
Let's see the related file tree first:&lt;br /&gt;
  /po: Contains all PO and POT files, as well as some updating tools.&lt;br /&gt;
  ---/blender.pot: The PO Template&lt;br /&gt;
  ---/*.po: All translations&lt;br /&gt;
  ---/POTFILES.in: All source files containing messages to be handled&lt;br /&gt;
  ---/update_pot.py: Script to update the blender.pot.&lt;br /&gt;
  ---/update_po.py: Script to update the *.po.&lt;br /&gt;
  ---/update_mo.py: Script to compile the *.po.&lt;br /&gt;
  /release/bin/.blender/locale: Contains all compiled translations.&lt;br /&gt;
  ----------------------------/*/LC_MESSAGES/blender.mo:&lt;br /&gt;
    Compiled translation for single language.&lt;br /&gt;
&lt;br /&gt;
====Update POT====&lt;br /&gt;
The update_pot.py will scan all the source files listed in the POTFILES.in. The command is like:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# --files-from specifies the files list&lt;br /&gt;
# --keyword specifies what indicates a target string&lt;br /&gt;
# --output specifies output file&lt;br /&gt;
# --from-code specifies string encode&lt;br /&gt;
xgettext --files-from=POTFILES.in&lt;br /&gt;
         --keyword=_ --keyword=N_&lt;br /&gt;
         --output=blender.pot&lt;br /&gt;
         --from-code=utf-8&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Generally, xgettext takes gettext() ans _() as default keywords, but it's not bad to repeat for clarity.&lt;br /&gt;
As you can see, in Garlic we also use another keyword, N_(). See details later.&lt;br /&gt;
&lt;br /&gt;
====Update PO====&lt;br /&gt;
The update_po.py will merge the blender.pot with all the PO files. After that, all additions, deletions and modifications of items will be available in the PO for translators. The command is like:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# --lang specifies the target language&lt;br /&gt;
# zh_CN.po is the old PO&lt;br /&gt;
# blender.pot is the updated PO Template&lt;br /&gt;
msgmerge --update --lang=zh_CN zh_CN.po blender.pot&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Update MO====&lt;br /&gt;
The update_mo.py will compile all the PO, generates MO files and put them under /release/bin/.blender/locale. The command is like:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# --statistics makes translation status printed&lt;br /&gt;
# zh_CN.po is the source PO&lt;br /&gt;
# -o specifies the target MO file path&lt;br /&gt;
msgfmt --statistics zh_CN.po -o LOCALE_DIR/zh_CN/LC_MESSAGES/blender.mo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===The _() and N_() Macro===&lt;br /&gt;
We supply a decorated gettext(), named BLF_gettext(), to do the real translation at runtime, which is in /source/blender/blenfont/intern/blf.c:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
const char* BLF_gettext(const char *msgid)&lt;br /&gt;
{&lt;br /&gt;
#ifdef INTERNATIONAL&lt;br /&gt;
	if( msgid!=NULL &amp;amp;&amp;amp; strlen(msgid)&amp;gt;0 )&lt;br /&gt;
		return gettext( msgid );&lt;br /&gt;
	return &amp;quot;&amp;quot;;&lt;br /&gt;
#else&lt;br /&gt;
	return msgid;&lt;br /&gt;
#endif&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Taking into account that it will be called thousands of times and we programers are lazy, a macro _() is supplied for short:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define _(msgid) BLF_gettext(msgid)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Please always try to use _(). It will make the code clearer, and translation related issues won't disturbe the logic semantics too much.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
However, sometimes we cannot call a function like BLF_gettext(). For example, there is piece of code in /source/blender/editors/screen/screen_ops.c:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static EnumPropertyItem modal_items[] = {&lt;br /&gt;
  {KM_MODAL_CANCEL, &amp;quot;CANCEL&amp;quot;, 0, &amp;quot;Cancel&amp;quot;, &amp;quot;&amp;quot;},&lt;br /&gt;
  {KM_MODAL_APPLY, &amp;quot;APPLY&amp;quot;, 0, &amp;quot;Apply&amp;quot;, &amp;quot;&amp;quot;},&lt;br /&gt;
  {KM_MODAL_STEP10, &amp;quot;STEP10&amp;quot;, 0, &amp;quot;Steps on&amp;quot;, &amp;quot;&amp;quot;},&lt;br /&gt;
  {KM_MODAL_STEP10_OFF, &amp;quot;STEP10_OFF&amp;quot;, 0, &amp;quot;Steps off&amp;quot;, &amp;quot;&amp;quot;},&lt;br /&gt;
  {0, NULL, 0, NULL, NULL}};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
We cannot call a function in these statements, but we need to let the xgettext command know what to collect. So, we seperate the gathering and translating stages as mentioned above. To achieve this we define a macro that do nothing. See it in /source/blender/blenfont/BLF_api.c:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define N_(msgid) msgid&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With this macro we can rewrite the code as:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static EnumPropertyItem modal_items[] = {&lt;br /&gt;
  {KM_MODAL_CANCEL, &amp;quot;CANCEL&amp;quot;, 0, N_(&amp;quot;Cancel&amp;quot;), &amp;quot;&amp;quot;},&lt;br /&gt;
  {KM_MODAL_APPLY, &amp;quot;APPLY&amp;quot;, 0, N_(&amp;quot;Apply&amp;quot;), &amp;quot;&amp;quot;},&lt;br /&gt;
  {KM_MODAL_STEP10, &amp;quot;STEP10&amp;quot;, 0, N_(&amp;quot;Steps on&amp;quot;), &amp;quot;&amp;quot;},&lt;br /&gt;
  {KM_MODAL_STEP10_OFF, &amp;quot;STEP10_OFF&amp;quot;, 0, N_(&amp;quot;Steps off&amp;quot;), &amp;quot;&amp;quot;},&lt;br /&gt;
  {0, NULL, 0, NULL, NULL}};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, all the marked strings can be gathered to POT. But where to do the real translating at runtime? The answer is any one place before its content takes effect. In this example, it's just in the same function:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
keymap= WM_modalkeymap_add( keyconf, &amp;quot;Standard Modal Map&amp;quot;, modal_items);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
We rewrite it as:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
keymap= WM_modalkeymap_add( keyconf, &amp;quot;Standard Modal Map&amp;quot;,&lt;br /&gt;
  RNA_enum_items_gettexted(modal_items));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The RNA_enum_items_gettexted() is defined in /source/blender/makesrna/intern/rna_access.c. It traverses over a EnumPropertyItem array, and try translating all name and description field:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* make every name and description field translated by gettext */&lt;br /&gt;
EnumPropertyItem* RNA_enum_items_gettexted(EnumPropertyItem *item)&lt;br /&gt;
{&lt;br /&gt;
  if( item )&lt;br /&gt;
  {&lt;br /&gt;
    int i;&lt;br /&gt;
    for(i=0; item[i].identifier; i++)&lt;br /&gt;
    {&lt;br /&gt;
      if( item[i].name )&lt;br /&gt;
        item[i].name = _(item[i].name);&lt;br /&gt;
      if( item[i].description )&lt;br /&gt;
        item[i].description = _(item[i].description);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return item;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===The Special makesrna Issues===&lt;br /&gt;
Most strings outside /source/blender/makesrna could be handled easily by _(). Both gathering and translating work well. But it's different for those inside the makesrna folder.&lt;br /&gt;
&lt;br /&gt;
When compiling, these files will linked as an executable makesrna, which will gennerate a lot of rna_*_gen.c somewhere depending on system. For linux, it's under [Build Path]/source/blender/makesrna/intern. These generated files will be compiled and linked into the final blender application.&lt;br /&gt;
&lt;br /&gt;
So there is no need to translate strings when running makesrna. We'll just use N_() to mark all strings we are interested in. To do the real translating, we should access the datas in generated files. This can be done by a extern declaration. See the makesrna/RNA_access.h for example:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
/* Types */&lt;br /&gt;
&lt;br /&gt;
extern BlenderRNA BLENDER_RNA;&lt;br /&gt;
extern StructRNA RNA_Action;&lt;br /&gt;
extern StructRNA RNA_ActionConstraint;&lt;br /&gt;
extern StructRNA RNA_ActionFCurves;&lt;br /&gt;
extern StructRNA RNA_ActionGroup;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Each of these StructRNAs contains a linked list of properties with name and description fields which should be translated. If it is an ENUM property, the item field would be an array of EnumPropertyItems mentioned above, so we also need to process it with RNA_enum_items_gettexted().&lt;br /&gt;
&lt;br /&gt;
Finally, we implement a RNA_types_init_gettext() in the makesrna/intern/rna_access.c to do this traversal processing.&lt;br /&gt;
&lt;br /&gt;
===Language Selection===&lt;br /&gt;
The application decides which translation to work with by both the locale and language settings. The language options are listed in an EnumPropertyItem array named language_items, in the /source/blender/makesrna/intern/rna_userdef.c. Users' selection is stored in the global U.language. So we can set the environment accordingly. This is all done in /source/blender/blenfont/intern/blf_lang.c. The most important function, BLF_lang_set(), will try setting the locale, LANG and LANGUAGE environment values to the specified language.&lt;br /&gt;
&lt;br /&gt;
This function also set the domain binding for gettext:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void BLF_lang_set(const char *str)&lt;br /&gt;
{&lt;br /&gt;
  ...&lt;br /&gt;
  if( str[0]!=0 )&lt;br /&gt;
  {&lt;br /&gt;
    BLI_setenv(&amp;quot;LANG&amp;quot;, str);&lt;br /&gt;
    BLI_setenv(&amp;quot;LANGUAGE&amp;quot;, str);&lt;br /&gt;
  }&lt;br /&gt;
  ...&lt;br /&gt;
  setlocale(LC_ALL, str);&lt;br /&gt;
  ...&lt;br /&gt;
  textdomain(DOMAIN_NAME);&lt;br /&gt;
  bindtextdomain(DOMAIN_NAME, global_messagepath);&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Font Loading===&lt;br /&gt;
Blender is rendered by OpenGL, so after other issues settled, the last problem is how to render international texts such as Chinese on the UI. The main point is to load a proper font when calling uiStyleInit() in /source/blender/editors/interface/interface_style.c. Finally we find  [http://unifoundry.com/unifont.html| Unifont] a good glyphs that support all useful utf8 characters.&lt;br /&gt;
&lt;br /&gt;
However, the TTF takes more than 10MB space. To make blender as lightweight as possible, we decide to gzip it. As a result, the application has to ungzip it at runtime. This work is done by BLI_ungzip_to_mem() in /source/blender/blenlib/intern/fileops.c:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/* &lt;br /&gt;
 * gzip the file in from_file and write it to memery to_mem,&lt;br /&gt;
 * at most size bytes.&lt;br /&gt;
 *&lt;br /&gt;
 * return the unziped size&lt;br /&gt;
 */&lt;br /&gt;
int BLI_ungzip_to_mem(const char *from_file, char *to_mem, const int size)&lt;br /&gt;
{&lt;br /&gt;
	gzFile gzfile;&lt;br /&gt;
	int readsize;&lt;br /&gt;
&lt;br /&gt;
	gzfile = gzopen( from_file, &amp;quot;rb&amp;quot; );&lt;br /&gt;
	readsize = gzread( gzfile, to_mem, size);&lt;br /&gt;
&lt;br /&gt;
	if (readsize &amp;lt; 0)&lt;br /&gt;
        readsize = EOF;&lt;br /&gt;
&lt;br /&gt;
	return readsize;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The get_datatoc_bunifont_ttf() function in /source/blender/editors/datafiles calls this function and return the font data been read. Then the uiStyleInit() finished loading the unifont TTF:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
font-&amp;gt;blf_id= BLF_load_mem_unique(&lt;br /&gt;
  &amp;quot;default&amp;quot;,&lt;br /&gt;
  (unsigned char *)get_datatoc_bunifont_ttf(),&lt;br /&gt;
  datatoc_bunifont_ttf_size);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Presently Garlic takes unifont as the default font, while not the old bfont. Because the Language Selection interface needs almost all languages, so any single language TTF may not work well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After these preparation, international texts can be displayed properly, now.&lt;br /&gt;
&lt;br /&gt;
{{Page/Footer|Internationalization|}}&lt;/div&gt;</summary>
		<author><name>wiki&gt;Xiaoxiangquan</name></author>
		
	</entry>
</feed>