Hello World Internationalized Sample App

The Internationalized Hello World sample app:

  • Launches a tab view when the app's icon is clicked.
  • Invokes a Yahoo! Mail API from the launched view.
  • Displays strings appropriate to the user's language preference..

Try It Out

See Quick Start to learn how to get the full source for this example, install it, and run it in Yahoo! Mail.

Changing your Language Preference

To try out this app's language features, you'll need to be able to switch your Yahoo! accounts language preference. To do that from within Yahoo! Mail:

  • Click on the "Hi, {your username}" menu in the upper left hand side of the browser
  • Select "Account Info"
  • Scroll down to "Account Settings" and click "Set language, site, time zone"
  • Switch your "Regional Site and Language" to, e.g. "Yahoo! France"

config.xml

This config.xml tells Yahoo! Mail to load your app's views/main in a tab when the app's icon is clicked. It also provides internationalized name and description tags for different languages.

  1. <?xml version="1.0"?>
  2. <openmail_app_config version="0">
  3. <name>Hello World (i18n)</name>
  4. <description>Hello World, internationalized version</description>
  5. <data/>
  6. <events>
  7. <click>
  8. <action>
  9. <launch>
  10. <view>main</view>
  11. <target_zone>tab</target_zone>
  12. </launch>
  13. </action>
  14. </click>
  15. </events>
  16. <intl_values>
  17. <intl_strings intl="en-AU">
  18. <name>Hello World</name>
  19. <description>Hello World, internationalized Version (en-AU)</description>
  20. <developer_name>Yahoo!</developer_name>
  21. <legal>
  22. <terms_of_service url="http://developer.yahoo.com/terms/"/>
  23. <privacy_policy url="http://info.yahoo.com/privacy/us/yahoo/devel/details.html"/>
  24. <landing_page url="http://developer.yahoo.com/"/>
  25. </legal>
  26. </intl_strings>
  27. <intl_strings intl="fr-FR">
  28. <name>Bonjour monde</name>
  29. <description>Bonjour monde, version internationalisée (fr-FR)</description>
  30. </intl_strings>
  31. </intl_values>
  32. </openmail_app_config>
  33.  
<?xml version="1.0"?>
<openmail_app_config version="0">
  <name>Hello World (i18n)</name>
  <description>Hello World, internationalized version</description>
  <data/>
  <events>
    <click>
      <action>
        <launch>
          <view>main</view>
          <target_zone>tab</target_zone>
        </launch>
      </action>
    </click>
  </events>
  <intl_values>
    <intl_strings intl="en-AU">
      <name>Hello World</name>
      <description>Hello World, internationalized Version (en-AU)</description>
      <developer_name>Yahoo!</developer_name>
      <legal>
          <terms_of_service url="http://developer.yahoo.com/terms/"/>
          <privacy_policy url="http://info.yahoo.com/privacy/us/yahoo/devel/details.html"/>
          <landing_page url="http://developer.yahoo.com/"/>
      </legal>
    </intl_strings>
    <intl_strings intl="fr-FR">
      <name>Bonjour monde</name>
      <description>Bonjour monde, version internationalisée (fr-FR)</description>
    </intl_strings>
  </intl_values>
</openmail_app_config>
 

views/main

main demonstrates how to pull in the Yahoo! Mail APIs and then use one of the API calls, Mail.compose. When the "Compose" button is clicked, the form invokes Mail.compose, which will open the mail composer with some fields prepopulated from the form based on the user's language preference.

fetchStrings fetches language-specific json based on the user's language, then invokes layoutDOM to apply those strings to the DOM, using both straight string substitution and template Y.lang.sub template substitution.

  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  5. <title>Hello World (i18n)</title>
  6. <script src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
  7. <script src="http://mail.yimg.com/nq/om/api/1.1.19/om-min.js"></script>
  8. </head>
  9. <body>
  10.  
  11. <p id="dailyFlood"></p>
  12.  
  13. <p><textarea id="tabody" cols="60" rows="10"></textarea></p>
  14.  
  15. <p>
  16. <button id="demobtn"></button>
  17. <input type="checkbox" value="rich" name="rich" id="richtext"/>
  18. <span id="checkboxTxt"></span>
  19. </p>
  20.  
  21. <script type="text/javascript">
  22.  
  23. YUI().use("node-base", "io-base", "json", function(Y) {
  24.  
  25. //Holds language-specific strings
  26. var STRINGS = {};
  27.  
  28. function init()
  29. {
  30. //compose button handler
  31. function demoCompose()
  32. {
  33. var bodyTxt = document.getElementById("tabody").value;
  34. var richText = document.getElementById("richtext").checked;
  35. var mailBlob = {
  36. to: STRINGS.sampleToAddress,
  37. cc: STRINGS.sampleCcAddress,
  38. bcc: STRINGS.sampleBccAddress,
  39. subject: STRINGS.sampleSubject,
  40. html: richText,
  41. body: bodyTxt
  42. };
  43.  
  44. openmail.Mail.compose(mailBlob);
  45. }
  46.  
  47. //Plug values from STRINGS into DOM components.
  48. //Hook up button click handler.
  49. function layoutDOM()
  50. {
  51. var messageCount = Math.floor(Math.random()*20000),
  52. target = document.getElementById("dailyFlood");
  53. target.innerHTML = Y.Lang.sub(STRINGS.dailyFloodInfo,
  54. {date : new Date(), number: messageCount});
  55.  
  56. target = document.getElementById("tabody");
  57. target.innerHTML = STRINGS.textAreaPrompt;
  58.  
  59. target = document.getElementById("demobtn");
  60. target.innerHTML = STRINGS.composeButton;
  61.  
  62. target = document.getElementById("checkboxTxt");
  63. target.innerHTML = STRINGS.richTextButton;
  64.  
  65. Y.on("click", demoCompose, "#demobtn");
  66. }
  67.  
  68. function onFetchStringsSuccess (transId, response, args)
  69. {
  70. if (response.responseText)
  71. {
  72. try {
  73. STRINGS = Y.JSON.parse(response.responseText);
  74. layoutDOM();
  75. } catch (x) {
  76. alert("Hello World's initialization failed.. try again later");
  77. openmail.Application.closeView();
  78. }
  79. }else{
  80. alert("Hello World failed to load resources.. try again later");
  81. openmail.Application.closeView();
  82. }
  83. }
  84.  
  85. function onFetchStringsFailure(transId, response, args)
  86. {
  87. alert("Hello World failed to load resources, try again later");
  88. openmail.Application.closeView();
  89. }
  90.  
  91. function fetchStrings(params)
  92. {
  93. //Default string resource bundle
  94. var url = "/yahoo/mail/assets/resources.json";
  95.  
  96. //user has language preference, use it for string definitions
  97. if(params.user.lang[0]){
  98. url = "/yahoo/mail/assets/resources_" + params.user.lang[0] + ".json";
  99. }
  100.  
  101. var cfg = {
  102. on: {
  103. success: onFetchStringsSuccess,
  104. failure: onFetchStringsFailure
  105. }
  106. };
  107.  
  108. //Fetch the strings from url
  109. Y.io(url, cfg);
  110.  
  111. }
  112.  
  113. //getParameters will callback to fetchStrings asynchrnously, passing the
  114. //user's language preference as part of the callback parameters.
  115. openmail.Application.getParameters(fetchStrings);
  116. }
  117.  
  118. Y.on("domready", init);
  119.  
  120. });
  121.  
  122. </script>
  123. </body>
  124. </html>
  125.  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   <title>Hello World (i18n)</title>
   <script src="http://yui.yahooapis.com/3.3.0/build/yui/yui-min.js"></script>
   <script src="http://mail.yimg.com/nq/om/api/1.1.19/om-min.js"></script>
</head>
<body>
 
<p id="dailyFlood"></p>
 
<p><textarea id="tabody" cols="60" rows="10"></textarea></p>
 
<p>
<button id="demobtn"></button>
<input type="checkbox" value="rich" name="rich" id="richtext"/>
<span id="checkboxTxt"></span>
</p>
 
<script type="text/javascript">
 
YUI().use("node-base", "io-base", "json", function(Y) {
 
    //Holds language-specific strings
    var STRINGS = {};
 
    function init()
    {  
        //compose button handler
        function demoCompose()
        {
            var bodyTxt = document.getElementById("tabody").value; 
            var richText = document.getElementById("richtext").checked;
            var mailBlob = {
                to: STRINGS.sampleToAddress,
                cc: STRINGS.sampleCcAddress,
                bcc: STRINGS.sampleBccAddress,
                subject: STRINGS.sampleSubject,
                html: richText,
                body: bodyTxt
            };
 
            openmail.Mail.compose(mailBlob);
        }
 
        //Plug values from STRINGS into DOM components.
        //Hook up button click handler.
        function layoutDOM() 
        {
            var messageCount = Math.floor(Math.random()*20000),
                target = document.getElementById("dailyFlood");
            target.innerHTML = Y.Lang.sub(STRINGS.dailyFloodInfo, 
                                          {date : new Date(), number: messageCount});
 
            target = document.getElementById("tabody");
            target.innerHTML = STRINGS.textAreaPrompt;
 
            target = document.getElementById("demobtn");
            target.innerHTML = STRINGS.composeButton;
 
            target = document.getElementById("checkboxTxt");
            target.innerHTML = STRINGS.richTextButton;
 
            Y.on("click", demoCompose, "#demobtn");
        }
 
        function onFetchStringsSuccess (transId, response, args)
        {
            if (response.responseText)
            {
                try {
                    STRINGS = Y.JSON.parse(response.responseText);
                    layoutDOM();
                } catch (x) {
                    alert("Hello World's initialization failed.. try again later");
                    openmail.Application.closeView();
                }
            }else{
                alert("Hello World failed to load resources.. try again later");
                openmail.Application.closeView();
            }
        }
 
        function  onFetchStringsFailure(transId, response, args)
        {
            alert("Hello World failed to load resources, try again later");
            openmail.Application.closeView();
        }
 
        function fetchStrings(params)
        {
            //Default string resource bundle
            var url = "/yahoo/mail/assets/resources.json";
 
            //user has language preference, use it for string definitions
            if(params.user.lang[0]){
                url = "/yahoo/mail/assets/resources_" + params.user.lang[0] + ".json";
            }
 
            var cfg = {
                on: {
                    success: onFetchStringsSuccess,
                    failure: onFetchStringsFailure
                }
            };
 
            //Fetch the strings from url
            Y.io(url, cfg);
 
        }
 
        //getParameters will callback to fetchStrings asynchrnously, passing the
        //user's language preference as part of the callback parameters.
        openmail.Application.getParameters(fetchStrings); 
    }
 
    Y.on("domready", init);
 
});
 
</script>
</body>
</html>
 

resources.json

This resources.json file provides default strings for when there are no strings specific to the user's language preference..

  1. {
  2. "dailyFloodInfo": "It's {date}. You have {number} new messages.",
  3. "textAreaPrompt": "Enter some text and press the \"Compose\" button.",
  4. "composeButton": "Compose",
  5. "richTextButton": "Rich text",
  6. "sampleToAddress": "hello@to.com",
  7. "sampleCcAddress": "hello@cc.com",
  8. "sampleBccAddress": "hello@bcc.com",
  9. "sampleSubject": "hello world"
  10. }
  11.  
{
    "dailyFloodInfo": "It's {date}. You have {number} new messages.",
    "textAreaPrompt": "Enter some text and press the \"Compose\" button.",
    "composeButton": "Compose",
    "richTextButton": "Rich text",
    "sampleToAddress": "hello@to.com",
    "sampleCcAddress": "hello@cc.com",
    "sampleBccAddress": "hello@bcc.com",
    "sampleSubject": "hello world"
}
 

resources_fr-FR.json

This resources_fr-FR.json file provides the French version of the strings.

  1. {
  2. "dailyFloodInfo": "Il est {date}. Vous avez {number} messages non lus.",
  3. "textAreaPrompt": "Entrez votre message et poussez \"Écrire\".",
  4. "composeButton": "Écrire",
  5. "richTextButton": "Texte riche",
  6. "sampleToAddress": "allo@à.fr",
  7. "sampleCcAddress": "allo@cc.fr",
  8. "sampleBccAddress": "allo@bcc.fr",
  9. "sampleSubject": "Bonjour le monde!"
  10. }
  11.  
  12.  
{
    "dailyFloodInfo": "Il est {date}. Vous avez {number} messages non lus.",
    "textAreaPrompt": "Entrez votre message et poussez \"Écrire\".",
    "composeButton": "Écrire",
    "richTextButton": "Texte riche",
    "sampleToAddress": "allo@à.fr",
    "sampleCcAddress": "allo@cc.fr",
    "sampleBccAddress": "allo@bcc.fr",
    "sampleSubject": "Bonjour le monde!"
}
 
 

resources_en-AU.json

This resources_fr-FR.json file provides the Australian English version of the strings.

  1. {
  2. "dailyFloodInfo": "tada! It’s {date}.You have {number} new messages.",
  3. "textAreaPrompt": "Enter some text and press the ”Compose” button.",
  4. "composeButton": "Compose",
  5. "richTextButton": "Rich text",
  6. "sampleToAddress": "hello@to.au",
  7. "sampleCcAddress": "hello@cc.au",
  8. "sampleBccAddress": "hello@bcc.au",
  9. "sampleSubject": "Hello World"
  10. }
  11.  
  12.  
{
    "dailyFloodInfo": "tada! It’s {date}.You have {number} new messages.",
    "textAreaPrompt": "Enter some text and press the ”Compose” button.",
    "composeButton": "Compose",
    "richTextButton": "Rich text",
    "sampleToAddress": "hello@to.au",
    "sampleCcAddress": "hello@cc.au",
    "sampleBccAddress": "hello@bcc.au",
    "sampleSubject": "Hello World"
}