Monday, 5 February 2018

Web Tutorial: Multilingual CNY Website (Part 2/3)

Welcome back...

One thing we didn't do in the last part was including a navigation bar. Because typing in the URLs constantly has got to be a gigantic pain in the butt. However, the navigational bar was left till now because it involves a new Model and Controller we'll be creating here.

Without further ado, let's create lang.rb in the models folder and langs_controller.rb in the controllers folder. Also create the view index.html.erb in the langs folder of the views folder, though we can pretty much leave it blank. The lang Model and Controller will be used application-wide, and aren't particular to any page.

lang.rb
class Lang

end


langs_controller.rb
class LangsController < ApplicationController
      def index

      end
end


In the Model, we're going to have different objects. And each object will have hashes as properties. Each hash will contain two key-value pairs - one for the English translation and the other for the Chinese translation.

lang.rb
class Lang
        def self.allowedVals
        {
            "languages" => Hash["en" => "English", "cn" => "中文"]
        }
        end

        def self.header
        {
            "header" => Hash["en" => "Happy New Year", "cn" => "新年快乐"],
        }
        end

        def self.labels
        {
            "language" => Hash["en" => "Language", "cn" => "语言"],
            "dogyears" => Hash["en" => "Dog Years", "cn" => "狗年"],
            "dogtraits" => Hash["en" => "Dog Traits", "cn" => "狗性格特征"],
            "dogfortune" => Hash["en" => "2018 Fortune", "cn" => "2018财富预测"],
            "tt" => Hash["en" => "Teochew Thunder", "cn" => "潮州雷"]
        }
        end
end


Open application_controller.rb in the controllers folder of the app folder. This is the application scope, and in it let's specify that get_langs() is always run before any actions of other controllers are executed.

application_controller.rb
class ApplicationController < ActionController::Base
        protect_from_forgery with: :exception

        before_action :get_langs
end


Then define the get_langs() routine. If there is no cookie named lang...

application_controller.rb
class ApplicationController < ActionController::Base
        protect_from_forgery with: :exception

        before_action :get_langs

        def get_langs
                if cookies[:lang] == nil

                end
        end
end


...create a cookie named lang with a value of "en". This basically means that we use the lang cookie to track what language the site is currently using. If there is no such cookie, the default is English.

application_controller.rb
class ApplicationController < ActionController::Base
        protect_from_forgery with: :exception

        before_action :get_langs

        def get_langs
               if cookies[:lang] == nil
                    cookies[:lang] =
                    {
                    :value => "en",
                    :expires => 1.year.from_now
                    }
                end
        end
end


Now, let's test this by altering the application template. Since we're using the Lang Model which is used sitewide, we'll reference its properties directly without going through its Controller. It's not a terribly beautiful solution, but I can live with it. See how we're using the value of the lang cookie, which is either "en" or "cn", as a key to the properties.

layouts\application.html.erb
<!DOCTYPE html>
<html>
    <head>
        <title><%=Lang.header["header"][cookies[:lang]]%></title>
        <%= csrf_meta_tags %>

        <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
        <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    </head>

    <body>
        <div class="container">
            <div class="header">
                <div class="headertext left">
                    <%=Lang.header["header"][cookies[:lang]]%>!
                </div>
                <div class="nav right">

                </div>
                <div class="clearfix"></div>
            </div>

            <div class="content">
                <%= yield %>
                <div class="clearfix"></div>
            </div>

            <div class="footer">
                <%=Lang.labels["tt"][cookies[:lang]]%> &copy; 2017
            </div>
        </div>
    </body>
</html>


Here, you'll see the values being displayed on-screen!




Now try this. This comments out the If condition and sets the lang cookie to "cn" no matter what.

application_controller.rb
class ApplicationController < ActionController::Base
        protect_from_forgery with: :exception

        before_action :get_langs

        def get_langs
            #if cookies[:lang] == nil
                   cookies[:lang] =
                   {
                   :value => "cn",
                   :expires => 1.year.from_now
                   }
           #end
        end
end


And now the displayed values have changed! But only the template has changed. The body is still in English. That's because the values in the Welcome Model are only in English. Let's fix that!



Instead of string values, we now have hashes containing "en" and "cn" keys, along with English and Chinese translations respectively.

welcome.rb
class Welcome
        def self.lang_content
        {
            "header" => Hash["en" => "Happy New Year", "cn" => "新年快乐"],
            "p1" => Hash["en" => "2018 is the Year of the Dog!", "cn" => "2018年是狗年!"],
            "p2" => Hash["en" => "Please click through the links above to find out more.", "cn" => "如果想了解更多,请点击上面的链接。"],
            "p3" => Hash["en" => "We wish you a happy and smooth-sailing New Year!", "cn" => "祝你新年快乐,万事如意!"]
        }
        end
end


And then we use the lang cookie's value to reference the appropriate key, in the Welcome Controller.

welcome_controller.rb
class WelcomeController < ApplicationController
      def index
            @header = Welcome.lang_content["header"][cookies[:lang]]
            @p1 = Welcome.lang_content["p1"][cookies[:lang]]
            @p2 = Welcome.lang_content["p2"][cookies[:lang]]
            @p3 = Welcome.lang_content["p3"][cookies[:lang]]
      end
end


Ah, now the body text has changed too. Let's get rid of the "Welcome" text. We no longer need it. It's taking up too much space on the display anyway.



welcome\index.html.erb
<div class="left">
    <p><%=@header %> </p>
    <p><%=@p1 %> </p>
    <p><%=@p2 %> </p>
    <p><%=@p3 %> </p>
</div>

<div class="right">
    <%= link_to image_tag("00.png");%>
</div>


Yep!



Now just repeat everything for the other Models, Controllers and Views. You'll notice that there's basically no change in the Year Model and Controller. As mentioned before, the years are four-digit strings and look the same in whatever language, so we took the lazy way out and just coded them straight in the View.

fortune.rb
class Fortune
        def self.lang_content
        {
            "p1" => Hash["en" => "According to traditional Chinese prediction, they will face several challenges in career and wealth. Although they may get enviable developments with rapid progress, they still need to keep modest all the time. Otherwise, the tense interpersonal relationship will likely do harm to their work and money.", "cn" => "根据中国传统的预测,他们将在职业和财富方面面临几个挑战。 虽然他们可能会得到令人羡慕的发展迅速进步,但仍然需要保持温和。 否则,紧张的人际关系可能会损害他们的工作和金钱。"],
            "p2" => Hash["en" => "Most of them are suitable to become group leaders. Their insistent and active personal traits will help them catch development opportunities. In the Year of the Dog, they are advised to do several investments related to cultural project or thermal power project. They are accustomed to earning profits by using strategy or even extreme methods.", "cn" => "他们大多数都适合成为集团领导人。 他们坚持和积极的个人特质将有助于他们抓住发展机遇。 在狗年中,建议与文化项目或火电项目进行多项投资。 他们习惯于通过使用策略甚至极端的方法赚取利润。"],
            "p3" => Hash["en" => "They should not be too self-willed and extreme in ordinary life. Staying calm down, thinking much and speaking little will bring good effects to their health situation. In addition, it is suggested to avoid some exploration activities such as climbing mountains, drifting and bungee jumping. Villa resort near river and forest is a wonderful place to take a holiday.", "cn" => "他们在日常生活中不应该太自私,极端。 保持冷静下来,思考多少,会对他们的健康状况产生好的效果。 此外,建议避免一些探险活动,如登山,漂流和蹦极跳跃。 靠近河流和森林的别墅度假是度过假期的绝佳去处。"]
        }
        end
end


trait.rb
class Trait
        def self.lang_content
        {
            "candid" => Hash["en" => "candid", "cn" => "坦率"],
            "loyal" => Hash["en" => "loyal", "cn" => "忠诚"],
            "intelligent" => Hash["en" => "intelligent", "cn" => "聪明"],
             "cool-headed" => Hash["en" => "cool-headed", "cn" => "冷静"],
            "persistent" => Hash["en" => "persistent", "cn" => "一贯"],
            "active" => Hash["en" => "active", "cn" => "活跃"],
            "impatient" => Hash["en" => "impatient", "cn" => "急躁"],
            "conservative" => Hash["en" => "conservative", "cn" => "保守"],
            "anxious" => Hash["en" => "anxious", "cn" => "焦急"]
        }
        end
end


year.rb
class Year
        def self.lang_content
        {

        }
        end
end


fortune_controller.rb
class FortuneController < ApplicationController
      def index
          @p1 = Fortune.lang_content["p1"][cookies[:lang]]
          @p2 = Fortune.lang_content["p2"][cookies[:lang]]
          @p3 = Fortune.lang_content["p3"][cookies[:lang]]
      end
end


traits_controller.rb
class TraitsController < ApplicationController
      def index
          @candid = Trait.lang_content["candid"][cookies[:lang]]
          @loyal = Trait.lang_content["loyal"][cookies[:lang]]
          @intelligent = Trait.lang_content["intelligent"][cookies[:lang]]
          @coolheaded = Trait.lang_content["cool-headed"][cookies[:lang]]
          @persistent = Trait.lang_content["persistent"][cookies[:lang]]
          @active = Trait.lang_content["active"][cookies[:lang]]
          @impatient = Trait.lang_content["impatient"][cookies[:lang]]
          @conservative = Trait.lang_content["conservative"][cookies[:lang]]
          @anxious = Trait.lang_content["anxious"][cookies[:lang]]
      end
end


year_controller.rb
class YearController < ApplicationController
      def index

      end
end


fortune\index.html.erb
<div class="left">
    <p><%=@p1 %> </p>
    <p><%=@p2 %> </p>
    <p><%=@p3 %> </p>
</div>

<div class="right">
    <%= link_to image_tag("01.png");%>
</div>


traits\index.html.erb
<div class="left">
    <p><%=@candid %> </p>
    <p><%=@loyal %> </p>
    <p><%=@intelligent %> </p>
    <p><%=@coolheaded %> </p>
    <p><%=@persistent %> </p>
    <p><%=@active %> </p>
    <p><%=@impatient %> </p>
    <p><%=@conservative %> </p>
    <p><%=@anxious %> </p>
</div>

<div class="right">
    <%= link_to image_tag("02.png");%>
</div>


fortune\index.html.erb
<div class="left">
    <h2>1982</h2>
    <h2>1994</h2>
    <h2>2006</h2>
    <h2>2018</h2>
    <h2>2030</h2>
</div>

<div class="right">
    <%= link_to image_tag("03.png");%>
</div>


Here's how all the other pages look with the newly selected language.










We're not done yet...

I promised to add a navigation bar, didn't I? We'll get on that now. Open the application.html.erb file from the layouts folder of the views folder.

We'll use the link_to helper for this. Read more on it here, but long story short, we get the appropriate URL by passing in the display string and a reference to the controller as arguments.

layouts\application.html.erb
                <div class="headertext left">
                    <%=link_to Lang.header["header"][cookies[:lang]], controller: "welcome" %>!
                </div>
                <div class="nav right">
                    <%=link_to Lang.labels["dogyears"][cookies[:lang]], controller: "years" %> |
                    <%=link_to Lang.labels["dogtraits"][cookies[:lang]], controller: "traits" %> |
                    <%=link_to Lang.labels["dogfortune"][cookies[:lang]], controller: "fortune" %>
                </div>


Try the links. They ought to work! Though it's not terribly obvious, the text on the left side is now a link that brings you back to the default page, which is Welcome.


Next

We'll implement a mechanism to switch languages at will. Watch for it!

No comments:

Post a Comment