Displaying skill rating for each skill on skill page of SUSI SKILL CMS

SUSI exhibits several skills which are managed by the SUSI Skill CMS, it essentially is a client which allows users to create/update skills conveniently since for each skill it is important to have the functionality of rating system so developers can get to know which skills are performing better than the rest and consequently improve them, thus a skill rating system which allows the users to give positive or negative feedback for each skill is implemented on the server.

Fetching skill_rating from the server

  1. Fetch skill data for which ratings are to be displayed through ajax calls
    API Endpoint –

    /cms/getSkillMetadata.json?
    

  2. Parse the received metadata object to get positive and negative ratings for that skill
  3. if(skillData.skill_rating) {
           	let positive_rating = skillData.skill_rating.positive;
            	let negative_rating = skillData.skill_rating.negative;
    }
    

    Sample API response

    {
      "skill_metadata": {
        "model": "general",
        "group": "Knowledge",
        "language": "en",
        "developer_privacy_policy": null,
        "descriptions": "Want to know about fossasia, just ask susi to tell that, Susi tells about the SUSI.AI creators",
        "image": "images/creator_info.png",
        "author": "madhav rathi",
        "author_url": "https://github.com/madhavrathi",
        "author_email": null,
        "skill_name": "Creator Info",
        "terms_of_use": null,
        "dynamic_content": false,
        "examples": [
          "Who created you?",
          "what is fossasia?"
        ],
        "skill_rating": {
          "negative": "0",
          "positive": "0",
          "stars": {
            "one_star": 0,
            "four_star": 0,
            "five_star": 0,
            "total_star": 0,
            "three_star": 0,
            "avg_star": 0,
            "two_star": 0
          },
          "feedback_count": 0
        },
        "creationTime": "2018-03-17T16:38:29Z",
        "lastAccessTime": "2018-06-15T15:51:50Z",
        "lastModifiedTime": "2018-03-17T16:38:29Z"
      },
      "accepted": true,
      "message": "Success: Fetched Skill's Metadata",
      "session": {"identity": {
        "type": "host",
        "name": "162.158.166.37_d80fb5c9",
        "anonymous": true
      }}
    }
    

  4. Set the react state of the component to store positive and negative rating.
  5. this.setState({
      positive_rating,
      negative_rating
    })
    

  6. Use react-icons to fetch like and dislike icon components from font-awesome.
  7. npm i -S react-icons
    

  8. Import the corresponding icons in the SkillPage component
  9. import { FaThumbsOUp, FaThumbsODown } from 'react-icons/lib/fa/'
    

  10. Display the rating count along with their icons
  11. <div className="rating">
        <div className="positive">
             <FaThumbsOUp />
             {this.state.positive_rating}
         </div>
           <div className="negative">
                 <FaThumbsODown />
                 {this.state.negative_rating}
             </div>
    </div>
    

Example

References

Initial Setups for Connecting SUSI Smart Speaker with iPhone/iPad

You may have experienced Apple HomPad, Google Home, Alexa etc or read about smart speakers that offer interactive action over voice commands. The smart speaker uses the hot word for activation. They utilize Wi-Fi, Bluetooth, and other wireless protocols.

SUSI.AI is also coming with Open Source smart speaker that can do various actions like playing music etc over voice commands. To use SUSI Smart Speaker, you have to connect it to the SUSI iOS or Android App. You can manage your connected devices in SUSI iOS, Android and Web clients. Here we will see initial setups for connecting SUSI Smart Speaker with iPhone/iPad (iOS Devices).

You may aware that iOS does not allow connecting to wifi within the app. To connect to a particular Wi-Fi, you have to go to phone settings, from there you can connect to Wi-Fi. SUSI Smart Speaker create a temporary Hotspot for initial setups. Follow the instruction below to connect to SUSI Smart Speaker hotspot –

  1. Tap to Home button, and go to your iPhone Settings > Wi-Fi
  2. Connect to the Wi-Fi hotspot for the device that you are setting up. It will have name “susi.ai”, like in the image below
  3. Come back to the SUSI app to proceed with setup.

These instruction is also available within the app when you are not connected to SUSI Smart Speaker hotspot and click `Setup a Device` or plus icon on Device Activity screen navigation bar.

Devices Activity and getting current Wi-Fi SSID:

Devices section in Settings screen shows the currently connected device. In Devices Activity screen, the user can manage the connected device. Only a logged-in user can access Devices Activity. When the user clicks on Device Accessories in setting, if the user is not logged-in, an alert is prompted with Login option. By clicking Login option, user directed to Login screen where the user can log in and come back to device section to proceed further.

If the user is already logged-in, Device Activity screen is presented. We use following method to scan if iPhone/iPad is connected to SUSI Smart Speaker:

func fetchSSIDInfo() -> String? {
var ssid: String?
if let interfaces = CNCopySupportedInterfaces() as? [String] {
for interface in interfaces {
if let interfaceInfo = CNCopyCurrentNetworkInfo(interface as CFString) as NSDictionary? {
ssid = interfaceInfo[kCNNetworkInfoKeySSID as String] as? String
break
}
}
}
return ssid
}

Apple’s SystemConfiguration API is used to get current Wi-Fi SSID. SystemConfiguration Allow applications to access a device’s network configuration settings. Determine the reachability of the device, such as whether Wi-Fi or cell connectivity is active.

import SystemConfiguration.CaptiveNetwork

The method above return the SSID of your device current Wi-Fi. SSID is simply the technical term for a network name. When you set up a wireless home network, you give it a name to distinguish it from other networks in your neighborhood. You’ll see this name when you connect your device to your wireless network.

If current Wi-Fi match with SUSI Smart Speaker hotspot, we display device in TableView, if not we display “No device connected yet”.

if let speakerSSID = fetchSSIDInfo(), speakerSSID == "susi.ai" {
cell.accessoryType = .disclosureIndicator
cell.textLabel?.text = speakerSSID
} else {
cell.accessoryType = .none
cell.textLabel?.text = "No device connected yet"
}

SUSI Smart Speaker is coming with very exciting features. Stay tuned.

Resources –

  1. SUSI iOS Link: https://github.com/fossasia/susi_iOS
  2. Apple’s SystemConfiguration Framework Documentation
  3. Bell’s article on What Do SSID and WPA2 mean

Post feedback for SUSI Skills in SUSI iOS

SUSI iOS, web and Android clients allow the user to rate the SUSI Skills in a 5-star rating system. Users can write about how much particular skill is helpful for them or if improvements are needed. Users can rate skills from one to five star as well. Here we will see how to submit feedback for SUSI skills and how it is implemented on SUSI iOS.

How to submit feedback –

  1. Go to Skill Listing Screen < Skill Detail Screen
  2. Scroll to the feedback section
  3. Write feedback about SUSI skill
  4. Click on POST button to post the skill feedback

An anonymous user can not submit skill feedback. You must have to logged-in in order to post skill feedback. If you are not logged-in and click POST button to post skill feedback, an alert is presented with Login option, by clicking Login, the user is directed to Login screen where the user can log in and later can post skill feedback.

Implementation of posting skill feedback –

Google’s Material textfield is used for skill feedback text field. We have assigned TextField class from Material target to skill feedback text field to make it very interactive and give better user experience.

Skill feedback text field in the normal state –

Skill feedback text field in the active state –

When the user clicks POST after writing skill feedback, we check if the user is logged-in or not.

if let delegate = UIApplication.shared.delegate as? AppDelegate, let user = delegate.currentUser {
...
}

We have saved the logged-in user globally using AppDelegate shared method during login and using it here. The AppDelegate is sort of like the entry point for the application. It implements UIApplicationDelegate and contains methods that are called when application launches, when is going to the background (i.e. when the user hit the home key), when it’s opened back up, and more. The AppDelegate object is stored as a property on the UIApplication class and is accessible from anywhere in swift classes.

Case 1: If the user is not logged-in, we show a popup to the user with the login option

By clicking Login, the user is directed to Login screen where the user can log in and later can post skill feedback.

Case 2: If the user is already logged-in, we use the endpoint below for posting skill feedback –

http://api.susi.ai/cms/feedbackSkill.json

ModelWith following parameters –

  • Group
  • Skill
  • Feedback
  • Access token
Client.sharedInstance.postSkillFeedback(postFeedbackParam) { (feedback, success, responseMessage) in
DispatchQueue.main.async {
if success {
self.skillFeedbackTextField.text = ""
self.skillFeedbackTextField.resignFirstResponder()
self.view.makeToast(responseMessage)
} else {
self.view.makeToast(responseMessage)
}
}
}

In return response, we get feedback posted by the user –

{
feedback: "Helpful",
session:
{
...
},
accepted: true,
message: "Skill feedback updated"
}

 

Resources –

  1. Material Design Guidelines for iOS
  2. Apple’s documentation on UIApplicationDelegate API
  3. Apple’s documentation on UIApplication API
  4. ChrisRisner’s article on Singletons and AppDelegate

Using a Git repo as a Storage & Managing skills through susi_skill_cms

In this post, I’ll be talking about SUSI’s skill management and the workflow of creating new skills

The SUSI skills are maintained in a separate github repository susi_skill_data which provides the features of version controlling and the ability to rollback to a previous version implemented in SUSI Server.

The workflow is as explained in the featured image of this blog, SUSI CMS provides the user with a GUI through which user can talk to the SUSI Server and using it’s api calls, it can manipulate the susi skills present/stored on the susi_skill_data repository.

When the user opts to create a new skill, a new createSkill component is loaded with an editor to define rules of the skill. Once the form is submitted, an AJAX POST request is made to the server which actually commits the skill data to the repository and thus it is visible in the CMS from that point on.

Grab the skill details within the editor and put them in a form which is to be sent via the POST request.

let form = new FormData();
form.append('model', 'general');
form.append('group', this.state.groupValue);
form.append('language', this.state.languageValue);
form.append('skill', this.state.expertValue.trim().replace(/\s/g,'_'));
form.append('image', this.state.file);
form.append('content', this.state.code);
form.append('image_name', this.state.imageUrl.replace('images/',''));
form.append('access_token', cookies.get('loggedIn'));


Configure POST request settings object

let settings = {
   'async': true,
   'crossDomain': true,
   'url': urls.API_URL + '/cms/createSkill.json',
   'method': 'POST',
   'processData': false,
   'contentType': false,
   'mimeType': 'multipart/form-data',
   'data': form
};


Make an AJAX request using the settings above to upload the skill to the server and send a notification when the request is successful.

$.ajax(settings)
   .done(function (response) {
   self.setState({
          loading:false
   });
notification.open({
    message: 'Accepted',
    description: 'Your Skill has been uploaded to the server',
    icon: <Icon type='check-circle' style={{ color: '#00C853' }}       />,
});


Parse the received response as JSON and if the accept key in the response is true, we push the new skill data to the history API and set relevant states.

let data = JSON.parse(response);
if(data.accepted===true){
  self.props.history.push({
	pathname: '/' + self.state.groupValue  +
  	'/' + self.state.expertValue.trim().replace(/\s/g,'_') +
  	'/' + self.state.languageValue,
	state: {
  	from_upload: true,
  	expertValue:  self.state.expertValue,
  	groupValue: self.state.groupValue ,
  	languageValue: self.state.languageValue,
}});


If the accepted key of the server response is not true, display a notification.

else{
	self.setState({
  		loading:false
	});
	notification.open({
	  	message: 'Error Processing your Request',
	  	description: String(data.message),
	  	icon: <Icon type='close-circle' style={{ color: '#f44336' }} />,
	});
}})


Handle cases when AJAX request fails and send a corresponding notification

.fail(function (jqXHR, textStatus) {
 ...
  notification.open({
    message: 'Error Processing your Request',
    description: String(textStatus),
    icon: <Icon type='close-circle' style={{ color: '#f44336' }} />,
  });
});


I hope after reading this post, the objectives of susi_skill_data are more clear and you understood how CMS handles the creation of skills.

Resources

1.AJAX Jquery – AJAX request using Jquery
2. React State – Read about React states and lifecycle hooks.

Comparison between SUSI AI with Mycroft AI and Amazon Alexa

Now is the era of Voice User Interface (VUI) devices and they play a very important role as personal assistants. Here we compare the SUSI AI, Mycroft AI and Amazon Alexa based on the number of skills, their availability, easiness to add and edit skills and the provision of the user to modify the skill and add more to it if needed, etc.

Issue: https://github.com/fossasia/labs.fossasia.org/issues/215

The Comparison:

  1. Starting with the number of skills, here Amazon Alexa supports way more number of skills as compared to both Mycroft AI and SUSI AI.
  2. Availability: Mycroft AI and SUSI AI are available everywhere and can set up anywhere regardless of the country whereas Alexa is available in U.S., U.K., Germany,  India but they are aggressively expanding.
  3. Adding and editing skills: Mycroft and SUSI are open source and their skills can be added and edited and viewed by the open source community. Issues can be made to enhance the functionality of the skills whereas Alexa skills are not open source and certification and publishing of the skill is done by the Amazon team. Mycroft and SUSI skills can be customized by the user but this fails with Alexa as users have to create that same skill from scratch if they have to customize them.
  4. Platforms supported: Mycroft, SUSI and Alexa all support Linux. Mycroft lacks support for Windows and Mac but supports Raspberry Pi and Android, Alexa provides support for Windows and Mac and Raspberry Pi. SUSI also provides support for Android and iOS and can be integrated with speakers, vehicles, Pi, etc.
  5. Dedicated devices: As of now SUSI AI lacks such device. Mycroft has Mark 1 and Alexa has Echo. These devices are portable and are good candidates for home automation.
  6. Languages used for skill development: Mycroft mostly uses python. Alexa uses python, NodeJS, C#, etc for development of applications. SUSI uses its own language but language like javascript can be included in it. It’s easier to specify patterns using wildcards and variables in SUSI.

Due to different languages used, Mycroft AI skills can’t be directly used in SUSI AI. We need to convert Mycroft skills to SUSI skills if Mycroft skills are to be used for SUSI.

Some suggestions for making a dedicated device for SUSI:

  1. We can use a Raspberry Pi, USB headphones and a microphone to make a basic platform.
  2. We can install Jasper to enable the voice input on the Pi. Jasper is a open source application that enables us to make voice controlled applications.
  3. We can use SUSI server to interact with the device and the home appliances like lights. SUSI server can process the states of the the appliance (lights in this case) and return it as JSON objects to Raspberry Pi and then it may change the state as per user input.

Make a simple Hello World skill with SUSI:

  1. Visit https://github.com/fossasia/susi_skill_cms/blob/master/docs/Skill_Tutorial.md for a basic introduction to SUSI skills syntax and how does it work.
  2. Go to http://dream.susi.ai .
  3. Enter the skill name, say “hello”.
  4. You will be greeted by a welcome message – “roses are red…..”. Delete it and replace it with the following snippet.
::name <Skill_name> #<— Enter skill name. for example hello

::author <author_name>

::author_url <author_url> #<— You can leave this empty as of now.

::description <description> #<— skill description

::dynamic_content No

::developer_privacy_policy <link> #<— you can leave this as of now.

::image <image_url> #<— You can leave this as of now.

::term_of_use <link>

#Intent. Comments are written with a #

hi|hello|what’s up #<— This is what the user says

Hi|I am good|Hello #<— This is what the skill answers

6. Now go to http://susi.ai/chat for the testing.

7. In the SUSI chat dialog box (present at the bottom of the page) enter dream <test application name> where “test application name” is the name you enter when you first visit http://dream.susi.ai. In this case “dream hello”.

8. You can input “what’s up” in the dialog box and it will give you the desired output which you mentioned in the application.

Conclusion:

SUSI has its own good points but it lacks in some department like the number and type of skills. Like Mycroft we can start making various skills and try to make a basic prototype of a dedicated SUSI personal assistant device.

Resources

  1. Jasper
  2. Skill addition to SUSI
  3. Mycroft hello world skill

 

Setting up SUSI Desktop Locally for Development and Using Webview Tag and Adding Event Listeners

SUSI Desktop is a cross platform desktop application based on electron which presently uses chat.susi.ai as a submodule and allows the users to interact with susi right from their desktop.

Any electron app essentially comprises of the following components

    • Main Process (Managing windows and other interactions with the operating system)
    • Renderer Process (Manage the view inside the BrowserWindow)

Steps to setup development environment

      • Clone the repo locally.
$ git clone https://github.com/fossasia/susi_desktop.git
$ cd susi_desktop
      • Install the dependencies listed in package.json file.
$ npm install
      • Start the app using the start script.
$ npm start

Structure of the project

The project was restructured to ensure that the working environment of the Main and Renderer processes are separate which makes the codebase easier to read and debug, this is how the current project is structured.

The root directory of the project contains another directory ‘app’ which contains our electron application. Then we have a package.json which contains the information about the project and the modules required for building the project and then there are other github helper files.

Inside the app directory-

  • Main – Files for managing the main process of the app
  • Renderer – Files for managing the renderer process of the app
  • Resources – Icons for the app and the tray/media files
  • Webview Tag

    Display external web content in an isolated frame and process, this is used to load chat.susi.ai in a BrowserWindow as

    <webview src="https://chat.susi.ai/"></webview>
    

    Adding event listeners to the app

    Various electron APIs were used to give a native feel to the application.

  • Send focus to the window WebContents on focussing the app window.
  • win.on('focus', () => {
    	win.webContents.send('focus');
    });
    
  • Display the window only once the DOM has completely loaded.
  • const page = mainWindow.webContents;
    ...
    page.on('dom-ready', () => {
    	mainWindow.show();
    });
    
  • Display the window on ‘ready-to-show’ event
  • win.once('ready-to-show', () => {
    	win.show();
    });
    

    Resources

    1. A quick article to understand electron’s main and renderer process by Cameron Nokes at Medium link
    2. Official documentation about the webview tag at https://electron.atom.io/docs/api/webview-tag/
    3. Read more about electron processes at https://electronjs.org/docs/glossary#process
    4. SUSI Desktop repository at https://github.com/fossasia/susi_desktop.

    Showing “Get started” button in SUSI Viber bot

    When we start a chat with SUSI.AI on Viber i.e. SUSI Viberbot, there should be an option on how to get started with the bot. The response to it are some options like “Visit repository”, “How to contribute” which direct the user to check how SUSI.AI bot is made and prompts him/her to contribute to it. Along with that an option of “start chatting” can be shown to add up some sample queries for the user to try.

    To accomplish the task at hand, we will accomplish these sub tasks:

    1. To show the “Get started” button.
    2. To show the reply to “Get started” query.
    3. To respond to the queries, nested in the response of “Get started”

    Showing “Get started”:

    The Viber developers platform notifies us when a user starts a conversation with our bot. To be exact, a conversation_started event is sent to our webhook and can be handled accordingly. The Viberbot shows a welcome message to the user along with a Get started button to help him/her start.

    To send just the welcome message:

    if (req.body.event === 'conversation_started') {
           // Welcome Message
           var options = {
               method: 'POST',
               url: 'https://chatapi.viber.com/pa/send_message',
               headers: headerBody,
               body: {
                   // some required body properties here
                   text: 'Welcome to SUSI.AI!, ' + req.body.user.name + '.',
                   // code for showing the get started button here.
            }
               json: true
           };
     
           request(options, function(error, res, body) {
               // handle error
           });
       }

    The next step is to show the “Get started” button. To show that we use a keyboard tool, provided by Viber developers platform. So after the “text” key we have the “keyboard” key and a value for it:

    keyboard: {
                 "Type": "keyboard",
                 "DefaultHeight": true,
                 "Buttons": [{
                     "ActionType": "reply",
                     "ActionBody": "Get started",
                 }]
             }

    The action type as shown in the code, can be “reply” or “open-url”. The “reply” action type, triggers an automatic query sent back with “Get started” (i.e. the value of “ActionBody” key), when that button gets clicked.

    Hence, this code helps us tackle our first sub task:

    Reply to “Get started”:

    We target to make each SUSI.AI bot generic. The SUSI FBbot and SUSI Tweetbot shows some options like “Visit repository”, “Start chatting” and “How to contribute?” for the “Get started” query. We render the same answer structure in Viberbot.

    The “rich_media” type helps us send buttons in our reply message. As we ought to use three buttons in our message, the button rows are three in the body object:

    if(message === "Get started"){
                       var options = {
                           method: 'POST',
                           url: 'https://chatapi.viber.com/pa/send_message',
                           headers: headerBody,
                           body: {
                               // some body object properties here
                               type: 'rich_media',
                               rich_media: {
                                   Type: "rich_media",
                                   ButtonsGroupColumns: 6,
                                   ButtonsGroupRows: 3,
                                   BgColor: "#FFFFFF",
                                   Buttons: buttons
                               }
                           },
                           json: true
                       };
     
                       request(options, function(error, res, body) {
                           if (error) throw new Error(error);
                           console.log(body);
                       });

    As said before, 2 type of Action types are available – “open-url” and “reply”. “Visit repository” button has an “open-url” action type and “How to contribute?” or “start chatting” has a “reply” action type.

    Example of “Visit repository” button:

    var buttons = [{
                    Columns: 6,
                    Rows: 1,
                    Text: "Visit repository",
                    "ActionType": "open-url",
                    "ActionBody": "https://www.github.com/fossasia/susi_server",
                    // some text styling properties here
                 }];

    To respond to the “reply” action type queries:

    When the “reply” action type button gets clicked, it triggers an automatic query sent back to the bot with the value same as that of the “ActionBody” key. So we just need to apply a check if the message string recieved is “Start chatting” or “How to contribute?”

    For the response to “Start chatting”, we plan to show sample queries for the user to try. This can be shown by using buttons with the action type as “reply”.

    Code snippet to show a button with the text as “What is FOSSASIA?”:

    var buttons = [{
                            Columns: 6,
                            Rows: 1,
                            Text: "What is FOSSASIA? ",
                            "ActionType": "reply",
                            "ActionBody": "What is FOSSASIA?",
                            // text styling here
                        }];

    For the response to “How to contribute”, we show some messages to help the user contribute to SUSI.AI. These messages also just need buttons with it, to be able to apply the necessary action.

    We respond with 2 messages to the user, both the messages have a button.

    For example, a button to visit the SUSI.AI Gitter channel:

    var buttons = [{
                        Columns: 6,
                        Rows: 1,
                           Text: "<font color=#323232><b>Chat on Gitter</b></font>",
                          ActionType: "open-url",
                          ActionBody: "https://www.gitter.im/fossasia/susi_server",
                          // text styling here
                }];

    This way we have successfully added the “Get started” option to our Viberbot and handled all the subsequent steps.

    Resources:

    1. Viber video managing chat extensions by Ingrid Lunden from Tech crunch.
    2. Develop a chat bot with node js by Slobodan Stojanović from smashing magazine.

    Creating Settings Screen in SUSI Android Using PreferenceActivity and Kotlin

    An Android application often includes settings that allow the user to modify features of the app. For example, SUSI Android app allows users to specify whether they want to use in built mic to give speech input or not. Different settings in SUSI Android app and their purpose are given below

    Setting                                        Purpose
    Enter As Send It allows users to specify whether they want to use enter key to send message or to add new line.
    Mic Input It allows users to specify whether they want to use in built mic to give speech input or not.
    Speech Always It allows users to specify whether they want voice output in case of speech input or not.
    Speech Output It allows users to specify whether they want speech output irrespective of input type or not.
    Language It allows users to set different query language.
    Reset Password It allows users to change password.
    Select Server It allows users to specify whether they want to use custom server or not.

    Android provides a powerful framework, Preference framework, that allows us to define the way we want preferences. In this blog post, I will show you how Settings UI is created using Preference framework and Kotlin in SUSI Android.

    Advantages of using Preference are:

    • It has own UI so we don‘t have to develop our own UI for it
    • It stores the string into the SharedPreferences so we don’t need to manage the values in SharedPreference.

    First, we will add the dependency in build.gradle(project) file as shown below.

    compile ‘com.takisoft.fix:preference-v7:25.4.0.3’

    To create the custom style for our Settings Activity screen we can set

    android:theme=“@style/PreferencesThemeLight”

    as the base theme and can apply various other modifications and colour over this. By default, it has the usual Day and Night theme with NoActionBar extension.

    Layout Design

    I used PreferenceScreen as the main container to create UI of Settings and filled it with the other components. Different components used are following:

    • SwitchPreferenceCompat: This gives us the Switch Preference which we can use to toggle between two different modes in the setting.
    <com.takisoft.fix.support.v7.preference.SwitchPreferenceCompat

    android:defaultValue=”true”

    • PreferenceCategory: It is used for grouping the preference. For example, Chat Settings, Mic Settings, Speech Settings etc are different groups in settings.

    • ListPreference: This preference display list of values and help in selecting one. For example in setLanguage option ListPreference is used to show a list of query language. List of query language is provided via xml file array.xml (res/values). Attribute android:entries point to arrays languagentries and android:entryValue holds the corresponding value defined for each of the languages.
    <ListPreference

    android:title=“@string/Language”
    android:key=“Lang_Select”

    android:entries=“@array/languagentries”

    android:entryValues=“@array/languagentry”

    </ListPreference>

    Implementation in SUSI Android

    All the logic related to Preferences and their action is written in ChatSettingsFragment class. ChatSettingsFragment extends PreferenceFragmentCompat class.

    class ChatSettingsFragment : PreferenceFragmentCompat()

    Fragment populate the preferences when created. addPreferencesFromResource method is used to inflate view from xml.

    addPreferencesFromResource(R.xml.pref_settings)

    Reference

    Implement Internationalization in SUSI Android With Weblate

    When you build an Android app, you must consider about users for whom you are building an app. It may be possible that you users are from the different region. To support the most users your app should show text in locale language so that user can use your app easily. Our app SUSI Android is also targeting users from different regions. Internationalization is a way that ensures our app can be adapted to various languages without requiring any change to source code. This also allows projects to collaborate with non-coders more easily and plugin translation tools like Weblate.

    Benefits of using Internationalization are:

    • It reduces the time for localization i.e it will localize your app automatically.
    • It helps us to keep and maintain only single source code for different regions.

    To achieve Internationalization in Android app you must follow below steps:

    • Move all the required contents of your app’s user interface into the resource file.
    • Create new directories inside res to add support for Internationalization. Each directory’s name should follow rule <resource type>-(language code). For example values-es contains string resource for es language code i.e Spanish.
    • Now add different locale content in the respective folder.

    We need to create separate directories for different locale because to show locale specific content, Android check specific folder i.e res/<resource type>-(language code) like res/values-de and show content from that folder. That’s why we need to move all the required content into resource file so that each required content can be shown in the specific locale.

    How Internationalization is implemented in SUSI Android

    In SUSI Android there is not any locale specific image but only string. So I created only locale specific value resource folder to add locale specific strings. To create locale specific values folder I follow the above-mentioned rule i.e <resource type>-(language code).

    After that, I added specific language string in the respective folder.

    Instead of hard-coded strings, we used strings from string.xml file so that it will change automatically according to the region.

    android:text=“@string/reset”

    and

    showToast(getString(R.string.wrong_password))

    In absence of resource directory for any specific locale, Android use default resource directory.

    Integrate Weblate in SUSI Android

    Weblate is a web based translation tool. The best part of Weblate is its tight version control integration which makes it easy for translators to contribute because translator does not need to fork your repo and send pull request for each change but Weblate handle this part i.e translator translate strings of the project in Weblate site and Weblate will send pull request for those changes.

    Weblate can host your free software projects for free but it depends on them. Here is the link of SUSI Android project hosted on Weblate. If your project is good then they can host your project for free. But for that, you have to apply from this link and select ask for hosting. Now fill up form as shown in below picture.

    Once your project is hosted on Weblate, they will email you about it. After that, you have to integrate Weblate in your project so that Weblate can automatically push translated strings to your project and also Weblate get notify about changes in your repository. Here is the link on how to add Weblate service and Weblate user to your project.

    If it is not possible to host your project on Weblate for free then you can host it by own. You can follow below steps:

    • First, we deploy Weblate on our localhost using the installation guide given on Weblate site. I install Weblate from git. I cloned latest source code using Git
    git clone https://github.com/WeblateOrg/weblate.git
    • Now change directory to where you cloned weblate source code and install all the required dependencies and optional dependencies using code
    pip install -r requirements.txt

    and

    pip install -r requirements-optional.txt
    • After doing that we copy weblate/settings_example.py to weblate/settings.py. Then we configure settings.py and use the following command to migrate the settings.
    ./manage.py migrate
    • Now create an admin using following command.
    ./manage.py createadmin
    • After that add a project from your Admin dashboard (Web translations-> Projects-> Add Project) by filling all details.
    • Once the project is added, we add the component (Web translations-> Components-> Add Component) to link our Translation files.
    • To change any translation we make changes and push it to the repository where our SSH key generated from Weblate is added. A full guide to do that is mentioned in this link.

    Reference