Skip to main content

Connected Arabic Characters for Android Apps

Another Android tutorial, driven by insomnia of having overdosed HPA Radix coffee.

Thank you Bro Ahmad Essam Naim, and Amr Gawish for providing the Arabic Reshaper class. The Java class is actually a library to reshape Arabic characters into connected forms. As we all know that Android 2.1 below do not support Arabic natively.

I’m assuming that you have the knowledge of Android apps development using Eclipse and already have the ADT installed.

STEP 1: Download the library at http://bar.amr-gawish.com/ .

After you have download and extract the file, you will have two files; ArabicReshaper.java, and ArabicUtilities.java . Copy both files in the src folder of your Android project.

More after the break… I’ll share on how to make use of the library.

BAR-Better Arabic Reshaper Logo

STEP 2: Download the Arabic supporting font.

In order to do this tutorial in the Android environment, please download Arabic font such as dejavu font available at http://dejavu-fonts.org/wiki/Main_Page .

Extraxt the file and put the font inside assets folder of your Android project.

You should have your files inside the Project Explorer as shown in the Figure 1.

image Figure 1: The position of the ArabicReshaper class and the DejaVu font in the project folder.

STEP 3: And this is the output.

image

These are the codes…

Code 1: arabicfont.java (just to display simple Unicode text in connected Arabic).

package com.kerul.arabicfont;
 
import android.app.Activity;
import android.content.res.AssetManager;
import android.graphics.Typeface;
import android.os.Bundle;
import android.widget.TextView;
import com.kerul.arabicfont.ArabicUtilities;
 
public class arabicfont extends Activity{
    AssetManager arabi_font;
    TextView tx;
 
    /** Called when the activity is first created. */
    @Override
 
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tx=(TextView)this.findViewById(R.id.tt);
    
        try{
            //DejaVuSans.ttf font file
            tx.setTypeface(Typeface.createFromAsset(getAssets(),"dejavusans.ttf"));
            //tx.setText("\uFEB3\uFE92\uFE98\uFE94");
            //tx.setText("\u0641\u0631\u0633");
            tx.setText(ArabicUtilities.reshape("\u0641\u0631\u0633"));//
            //tx.setText("hello");
        }
        
        
        catch(Exception ex){
            tx.setText("font cannot load: "+ ex.toString() );
        } 
            
        
    }
}

Code 2: ArabicReshaper.java



package com.kerul.arabicfont;
 
/*
 *    Date : 25th of March 2008
 *    the class is Arabic string reshaper, this class is targeting Android platform
 *
 *     By        : Ahmed Essam Naiem
 *  E-Mail     : ahmed-essam@live.com
 *  Web        : www.ahmed-essam.com
 *  
 *  Updated Date : 20 of March 2009
 *  The class has been updated to include the Lam Alef Reshaping techniques
 *  
 *  By        : Amr Ismail gawish
 *  Email   : amr.gawish@gmail.com
 *  Web        : www.amr-gawish.com
 *  
 *  Updated : 8th of June 2009
 *  Adding comments and Announcing Open Source
 *  
 *  
 *  By        : Ahmed Essam Naiem
 *  E-Mail    : ahmed-essam@live.com
 *  Web        : www.ahmed-essam.com
 *  
 *  Update    : Sunday 7th of February 2010 
 *  Fixing the Harakat (Fatha, Dama, etc ...), still has bug in the 2nd character and last character correct character shape
 * */
import java.lang.String;
/**
 * This class is the main class that is responsible for Reshaping Arabic Word
 * The Reshaping Engine
 * It's role is to provide the right form of the word.
 * @author Ahmed Essam Naiem, Amr Ismail Gawish
 */
public class ArabicReshaper{
    /**
     * The reshaped Word String
     */
    private String _returnString;
 
 
    /**
     * The Reshaped Word
     * @return reshaped Word
     */
    public String getReshapedWord(){
 
        return _returnString;
    }
 
    /**
     * Alef with Madd like "اّمن"
     */
    public static char DEFINED_CHARACTERS_ORGINAL_ALF_UPPER_MDD = 0x0622;
 
    /**
     * Alef with Hamza on the Upper like "أحمد"
     */
    public static char DEFINED_CHARACTERS_ORGINAL_ALF_UPPER_HAMAZA = 0x0623;
 
    /**
     * Alef with Hamza on the Lower Like "إبراهيم"
     */
    public static char DEFINED_CHARACTERS_ORGINAL_ALF_LOWER_HAMAZA = 0x0625;
 
    /**
     * The Alef Character "ÿß"
     */
    public static char DEFINED_CHARACTERS_ORGINAL_ALF = 0x0627;
 
    /**
     * The Lam Character "ŸÑ"
     */
    public static char DEFINED_CHARACTERS_ORGINAL_LAM    =0x0644;
 
 
 
    /**
     * The All Lam Forms in the [0] element
     * With all its forms either at the end of the word, or in the middle of the word in [1][2] respectively
     */
    public static char[][] LAM_ALEF_GLPHIES=
    {{15270,65270,65269},
     {15271,65272,65271},
     {1575, 65276,65275},
     {1573, 65274,65273}
    };
 
    /**
     * All Arabic Letters with It's different Forms
     * [0] Element is the letter Alone
     * [1][2][3][4] are all the forms of the Letter
     * [5] is the number of Forms the Letter has
     * 
     * If "ÿß" It has only two forms : "ŸÄÿß" and "ÿß"
     * If "ب" It has only four forms : "بـ", "ـبـ", "ـب" and "ب"
     * and so on
     */
    
    // The Array is sorted to be able to use the binary search, please don't miss with it.
    public static char[][] ARABIC_GLPHIES=
           {{ 1569,65152,65163,65164,65152,3 } ,
            { 1570,65153,65153,65154,65154,2 } ,
            { 1571,65155,65155,65156,65156,2 } ,
            { 1572,65157,65157,65158,65158,2 } ,
            { 1573,65159,65159,65160,65160,2 } ,
            { 1574,65161,65161,65162,65162,2 } ,
            { 1575,65165,65165,65166,65166,2 } ,
            { 1576,65167,65169,65170,65168,4 } ,
            { 1577,65171,65171,65172,65172,2 } ,
            { 1578,65173,65175,65176,65174,4 } ,
            { 1579,65177,65179,65180,65178,4 } ,
            { 1580,65181,65183,65184,65182,4 } ,
            { 1581,65185,65187,65188,65186,4 } ,
            { 1582,65189,65191,65192,65190,4 } ,
            { 1583,65193,65193,65194,65194,2 } ,
            { 1584,65195,65195,65196,65196,2 } ,
            { 1585,65197,65197,65198,65198,2 } ,
            { 1586,65199,65199,65200,65200,2 } ,
            { 1587,65201,65203,65204,65202,4 } ,
            { 1588,65205,65207,65208,65206,4 } ,
            { 1589,65209,65211,65212,65210,4 } ,
            { 1590,65213,65215,65216,65214,4 } ,
            { 1591,65217,65219,65218,65220,4 } ,
            { 1592,65221,65223,65222,65222,4 } ,
            { 1593,65225,65227,65228,65226,4 } ,
            { 1594,65229,65231,65232,65230,4 } ,
            { 1601,65233,65235,65236,65234,4 } ,
            { 1602,65237,65239,65240,65238,4 } ,
            { 1603,65241,65243,65244,65242,4 } ,
            { 1604,65245,65247,65248,65246,4 } ,
            { 1605,65249,65251,65252,65250,4 } ,
            { 1606,65253,65255,65256,65254,4 } ,
            { 1607,65257,65259,65260,65258,4 } ,
            { 1608,65261,65261,65262,65262,2 } ,
            { 1609,65263,65263,65264,65264,2 } ,            
            { 1610,65265,65267,65268,65266,4 } };
 
    /**
     * Binary search for the character, it returns the index of the character in the array. 
     * @param start,     the start point for the binary search
     * @param end,         the end point for the binary search
     * @param target,     the character that is function looking for
     * @return The index of the found character.
     */
    private int findGlphy(int start,int end,char target){
        if(start<0)
            return -1;
        if(end>35)
            return -1;
        
        int middle = start + ((end - start)/2);
        if(middle<end)
            if(ARABIC_GLPHIES[middle+1][0]==target)
                return middle+1;
        if (ARABIC_GLPHIES[middle][0]==target)
            return middle;
        if(end-middle==1)
            return -1;
        if(ARABIC_GLPHIES[middle][0]<target)
            return findGlphy(middle, end, target);
        if(ARABIC_GLPHIES[middle][0]>target)
            return findGlphy(start, middle, target);
        return -1;
    }
    
 
    /**
     * Searching for the letter and Get the right shape for the character depends on the location specified 
     * @param target The character that needs to get its form
     * @param location The location of the Form letter
     * @return The letter with its right shape
     */
    private char getReshapedGlphy(char target,int location){
        int found = findGlphy(0, 35, target);
        if(found==-1)
            return target;
        return ARABIC_GLPHIES[found][location];
    }
 
    /**
     * The function should return the correct Glphy type for the caller, the function Escape any character like "7arakat"
     * @param target     The character, that needed 
     * @param location     The location of the character to be return its type
     * @return the integer number indicated the Number of forms the Character has, return 2 otherwise
     */
    private int getGlphyTypeBefore(String wholeTarget,int location){
        if(location==0)
            return 2;
        char target = wholeTarget.charAt(location);
        int foundGlphy = findGlphy(0,35,target);
        if(foundGlphy==-1){
            location--;
            return getGlphyTypeBefore(wholeTarget, location);
        }
        return ARABIC_GLPHIES[foundGlphy][5];        
    }
    
    /**
     * Define which Character Type is This, that has 2,3 or 4 Forms variation?
     * @param target The character, that needed 
     * @return the integer number indicated the Number of forms the Character has, return 2 otherwise
     */
    private int getGlphyType(String wholeTarget,int location){
        char target = wholeTarget.charAt(location);
        
        // Something Magical should happen here
        int n = findGlphy(0, 35, target);
        if(n==-1)
            return 2;
        return ARABIC_GLPHIES[n][5];
    }
 
 
    /**
     * Get LamAlef right Character Presentation of the character
     * @param candidateAlef The letter that is supposed to Alef
     * @param candidateLam The letter that is supposed to Lam
     * @param isEndOfWord Is those characters at the end of the Word, to get its right form 
     * @return Reshaped character of the LamAlef
     */
    private char getLamAlef(char candidateAlef,char candidateLam,boolean isEndOfWord){
        //The shift rate, depends if the the end of the word or not!
        int shiftRate = 1;
 
        //The reshaped Lam Alef
        char reshapedLamAlef=0;
 
        //Check if at the end of the word
        if(isEndOfWord)
            shiftRate++;
 
        //check if the Lam is matching the candidate Lam
        if((int)DEFINED_CHARACTERS_ORGINAL_LAM ==(int)candidateLam){
 
            //Check which Alef is matching after the Lam and get Its form
            if((int)candidateAlef ==(int)DEFINED_CHARACTERS_ORGINAL_ALF_UPPER_MDD){
                reshapedLamAlef = LAM_ALEF_GLPHIES[0][shiftRate];
            }
 
            if((int)candidateAlef ==(int)DEFINED_CHARACTERS_ORGINAL_ALF_UPPER_HAMAZA){
                reshapedLamAlef = LAM_ALEF_GLPHIES[1][shiftRate];
            }
 
            if((int)candidateAlef ==(int)DEFINED_CHARACTERS_ORGINAL_ALF_LOWER_HAMAZA){
                reshapedLamAlef = LAM_ALEF_GLPHIES[3][shiftRate];
            }
 
            if((int)candidateAlef ==(int)DEFINED_CHARACTERS_ORGINAL_ALF){
                reshapedLamAlef = LAM_ALEF_GLPHIES[2][shiftRate];
            }
        }
        //return the ReshapedLamAlef
        return reshapedLamAlef;
    }
 
 
    /**
     * Constructor of the Class
     * It doesn't support Alef Lam by Default
     * @param unshapedWord The unShaped Word
     */
    public ArabicReshaper(String unshapedWord){
        _returnString=reshapeIt(unshapedWord);
    }
 
 
    /**
     * The Enhanced Arabic Reshaper Constructor with Lam Alef Support
     * @param unshapedWord The unShaped Word
     * @param supportAlefLam To check If to support AlefLam or Not
     */
    public ArabicReshaper(String unshapedWord,boolean supportAlefLam){
        if(!supportAlefLam) {
            _returnString=reshapeIt(unshapedWord);
        }else {
            _returnString=reshapeItWithLamAlef(unshapedWord);
        }
    }
 
    /**
     * Main Reshaping function, Doesn't Support LamAlef
     * @param unshapedWord The unReshaped Word to Reshape
     * @return The Reshaped Word without the LamAlef Support
     */
    public String reshapeIt(String unshapedWord){
 
        //The reshaped Word to Return
        StringBuffer reshapedWord=new StringBuffer("");
 
        //The Word length
        int wordLength = unshapedWord.length();
 
        //The Word Letters
        char [] wordLetters = new char[wordLength];
 
        //Copy the unreshapedWord to the WordLetters Character Array
        unshapedWord.getChars(0, wordLength, wordLetters,0 );
 
 
        //for the first letter
        reshapedWord.append(getReshapedGlphy(wordLetters[0], 2));//2 is the Form when the Letter is at the start of the word
 
 
        //iteration from the second till the second to last
        for(int i=1;i<wordLength-1;i++){
            int beforeLast=i-1;
                //Check if the Letter Before Last has only 2 Forms, for the current Letter to be as a start for a new Word!
                if(getGlphyTypeBefore(unshapedWord,beforeLast)==2){ //checking if it's only has 2 shapes
                    //If the letter has only 2 shapes, then it doesnt matter which position it is, It'll be always the second form
                    reshapedWord.append(getReshapedGlphy(wordLetters[i], 2));
                }else {
                    //Then it should be in the middle which should be placed in its right form [3]
                    reshapedWord.append(getReshapedGlphy(wordLetters[i], 3));
                }
        }
 
        //check for the last letter Before last has 2 forms, that means that the last Letter will be alone.
        if(getGlphyTypeBefore(unshapedWord,wordLength-2)==2){
            //If the letter has only 2 shapes, then it doesnt matter which position it is, It'll be always the second form
            reshapedWord.append(getReshapedGlphy(wordLetters[wordLength-1], 1));
        }else {
            //Put the right form of the character, 4 for the last letter in the word
            reshapedWord.append(getReshapedGlphy(wordLetters[wordLength-1], 4));
        }
 
        //Return the ReshapedWord
        return reshapedWord.toString();
    }
 
 
    /**
     * Main Reshaping Function, With LamAlef Support
     * @param unshapedWord The UnReshaped Word
     * @return The Shaped Word with Lam Alef Support
     */
    public String reshapeItWithLamAlef(String unshapedWord){
 
        //The reshaped Word to Return
        StringBuffer reshapedWord=new StringBuffer("");
 
        //The Word length
        int wordLength = unshapedWord.length();
 
        //The Word Letters
        char [] wordLetters = new char[wordLength];
 
        //The reshaped Letters
        char [] reshapedLetters=new char[wordLength];
 
        //Indicator Character, to Tell that lam is exist
        char lamIndicator=43;//The '+' 
 
        //Copy the unreshapedWord to the WordLetters Character Array
        unshapedWord.getChars(0, wordLength, wordLetters,0 );
 
        //Check if the Word Length is 0, then return empty String
        if(wordLength==0){
            return "";
        }
 
        //Check if the Word length is 1, then return the Reshaped One letter, which is the same character of input
        if(wordLength==1){
            return getReshapedGlphy(wordLetters[0],1)+"";
        }
 
        //Check if the word length is 2, Check if the Word is LamAlef 
        if(wordLength==2){
            //Assign Candidate Lam
            char lam=wordLetters[0];
 
            //Assign Candidate Alef
            char alef=wordLetters[1];
 
            //Check if The word is Lam Alef.
            if(getLamAlef(alef, lam, true)>0){
                return (char)getLamAlef(alef,lam,true)+" ";
            }
 
        }
 
        //For the First Letter
        reshapedLetters[0]=getReshapedGlphy(wordLetters[0], 2);
 
        //The current Letter
        char currentLetter=wordLetters[0];
 
        /**
         * The Main Iterator
         */
 
        //Iterate over the word from the second character till the second to the last
        for(int i=1;i<wordLength-1;i++){
 
            //Check if the Letters are Lam Alef
            if(getLamAlef(wordLetters[i], currentLetter, true)>0){
                //Check if the Letter before the Lam is 2 Forms Letter, to Make the Lam Alef as its the end of the Word
                if(getGlphyTypeBefore(unshapedWord, i-2)==2){
 
                    //Mark the letter of Lam as Lam Indicator
                    reshapedLetters[i-1]=lamIndicator;
 
                    //Assign Lam Alef to the Letter of Alef
                    reshapedLetters[i]=(char)getLamAlef(wordLetters[i], currentLetter, true);
 
                }else{ //The Letter before the Lam is more than 2 Forms Letter
 
                    //Mark the letter of Lam as Lam Indicator
                    reshapedLetters[i-1]=lamIndicator;
 
                    //Assign Lam Alef to the Letter of Alef
                    reshapedLetters[i]=(char)getLamAlef(wordLetters[i], currentLetter, false);
                }
            }else{ //The Word doesn't have LamAlef
 
                int beforeLast=i-1;
 
                //Check if the Letter Before Last has only 2 Forms, for the current Letter to be as a start for a new Word!
                if(getGlphyTypeBefore(unshapedWord, beforeLast)==2){
 
                    //If the letter has only 2 shapes, then it doesnt matter which position it is, It'll be always the second form
                    reshapedLetters[i]=getReshapedGlphy(wordLetters[i], 2);
                }else{
 
                    //Then it should be in the middle which should be placed in its right form [3]
                    reshapedLetters[i]=getReshapedGlphy(wordLetters[i], 3);
                }
            }
            //Assign the CurrentLetter as the Word Letter
            currentLetter=wordLetters[i];
        }
 
 
        /**
         * The Last Letters Check
         */
 
        //Check if the Letters are Lam Alef
        if(getLamAlef(wordLetters[wordLength-1], wordLetters[wordLength-2], true)>0){
 
            //Check if the Letter before the Lam is 2 Forms Letter, to Make the Lam Alef as its the end of the Word
            if(getGlphyType(unshapedWord,wordLength-3)==2){ //check for the last letter
 
                //Mark the letter of Lam as Lam Indicator
                reshapedLetters[wordLength-2]=lamIndicator;
 
                //Assign Lam Alef to the Letter of Alef
                reshapedLetters[wordLength-1]=(char)getLamAlef(wordLetters[wordLength-1], wordLetters[wordLength-2], true);
            }else {
 
                //Mark the letter of Lam as Lam Indicator
                reshapedLetters[wordLength-2]=lamIndicator;
 
                //Assign Lam Alef to the Letter of Alef
                reshapedLetters[wordLength-1]=(char)getLamAlef(wordLetters[wordLength-1], wordLetters[wordLength-2], false);
            }
 
        }else { 
            //check for the last letter Before last has 2 forms, that means that the last Letter will be alone.
            if(getGlphyType(unshapedWord,wordLength-2)==2){
                //If the letter has only 2 shapes, then it doesn't matter which position it is, It'll be always the second form
                reshapedLetters[wordLength-1]=getReshapedGlphy(wordLetters[wordLength-1], 1);
            }else {
                //Put the right form of the character, 4 for the last letter in the word
                reshapedLetters[wordLength-1]=getReshapedGlphy(wordLetters[wordLength-1], 4);
            }
        }
 
        /**
         * Assign the Final Results of Shaped Word
         */
 
        //Iterate over the Reshaped Letters and remove the Lam Indicators
        for(int i=0;i<reshapedLetters.length;i++){
 
            //Check if the Letter is Lam Indicator
            if(reshapedLetters[i]!=lamIndicator)
                reshapedWord.append(reshapedLetters[i]);
        }
 
        //Return the Reshaped Word
        return reshapedWord.toString();
    }    
}

Code 3: ArabicUtilities.java



package com.kerul.arabicfont;
 
/*
 *    Date : 8th of June 2009
 *    the class is Arabic string reshaper Utilities, this class is targeting Android platform
 *
 *     By        : Amr Ismail Gawish
 *  E-Mail     : amr.gawish@gmail.com
 *  Web        : http://www.amr-gawish.com
 *  
 *  Updated : 8th of June 2009
 *  Adding comments and Announcing Open Source
 *  
 * Updated: 6th of May 2010
 * Enahancing Functionality by Amine : bakhtout@gmail.com
 *
 * */
import java.util.ArrayList;
 
import android.content.Context;
import android.graphics.Typeface;
import android.view.Gravity;
import android.widget.TextView;
 
/**
 * This class is the main class that is responsible for Reshaping Arabic Sentences and Text
 * Utilities Class to make it easier to deal with Arabic Reshaper Class
 * Wrapper for Arabic Reshaper Class
 * @author Amr Gawish
 */
public class ArabicUtilities {
 
         /**
     * the path of teh fonts file must be under assets folder
     */
    private static final String FONTS_LOCATION_PATH = "fonts/DejaVuSans.ttf";
 
 
 
    /**
     * Helper function is to check if the character passed, is Arabic
     * @param target The Character to check Against
     * @return true if the Character is Arabic letter, otherwise returns false
     */
    private static boolean isArabicCharacter(char target){
 
        //Iterate over the 36 Characters in ARABIC_GLPHIES Matrix
        for(int i = 0; i < ArabicReshaper.ARABIC_GLPHIES.length;i++){
            //Check if the target Character exist in ARABIC_GLPHIES Matrix
            if(ArabicReshaper.ARABIC_GLPHIES[i][0]==target)
                return true;
        }
 
        return false;
    }
 
    /**
     * Helper function to split Sentence By Space
     * @param sentence the Sentence to Split into Array of Words
     * @return Array Of words
     */
    private static String[] getWords(String sentence){
        if (sentence != null) {
            return sentence.split("\\s");
        } else {
            return new String[0];
        }
    }
 
    /**
     * Helper function to check if the word has Arabic Letters
     * @param word The to check Against
     * @return true if the word has Arabic letters, false otherwise
     */
    public static boolean hasArabicLetters(String word){
 
        //Iterate over the word to check all the word's letters
        for(int i=0;i<word.length();i++){
 
            if(isArabicCharacter(word.charAt(i)))
                return true;
        }
        return false;
    }
 
    /**
     * Helper function to check if the word is all Arabic Word
     * @param word The word to check against
     * @return true if the word is Arabic Word, false otherwise
     */
    public static boolean isArabicWord(String word){
        //Iterate over the Word
        for(int i=0;i<word.length();i++){
            if(!isArabicCharacter(word.charAt(i)))
                return false;
        }
        return true;
    }
 
    /**
     * Helper function to split the Mixed Word into words with only Arabic, and English Words
     * @param word The Mixed Word
     * @return The Array of the Words of each Word may exist inside that word
     */
    private static String[] getWordsFromMixedWord(String word){
 
        //The return result of words
        ArrayList<String> finalWords=new ArrayList<String>();
 
        //Temp word to hold the current word
        String tempWord="";
 
        //Iterate over the Word Length
        for(int i=0;i<word.length();i++){
 
            //Check if the Character is Arabic Character
            if(isArabicCharacter(word.charAt(i))){
 
                //Check if the tempWord is not empty, and what left in tempWord is not Arabic Word
                if(!tempWord.equals("") && !isArabicWord(tempWord)) {
 
                    //add the Word into the Array
                    finalWords.add(tempWord);
 
                    //initiate the tempWord again
                    tempWord=""+word.charAt(i);
 
                }else{
 
                    //Not to add the tempWord, but to add the character to the rest of the characters
                    tempWord+=word.charAt(i);
                }
 
            }else{
 
                //Check if the tempWord is not empty, and what left in tempWord is Arabic Word
                if(!tempWord.equals("") && isArabicWord(tempWord)){
 
                    //add the Word into the Array
                    finalWords.add(tempWord);
 
                    //initiate the tempWord again
                    tempWord=""+word.charAt(i);
 
                }else{
 
                    //Not to add the tempWord, but to add the character to the rest of the characters
                    tempWord+=word.charAt(i);
                }
            } 
        }
 
        String[] theWords=new String[finalWords.size()];
        theWords=(String[])finalWords.toArray(theWords);
 
        return theWords;
    }
 
    public static String reshape(String allText) {
        if (allText != null) {
            StringBuffer result = new StringBuffer();
            String[] sentences = allText.split("\n");
            for (int i = 0; i < sentences.length; i++) {
                result.append(reshapeSentence(sentences[i]));
                result.append("\n");
            }
            return result.toString();
        } else {
            return null;
        }
        
    }
    /**
     * The Main Reshaping Function to be Used in Android Program
     * @param allText The text to be Reshaped
     * @return the Reshaped Text
     */
    public static String reshapeSentence(String sentence){
            
            //get the Words from the Text
            String[] words=getWords(sentence);
 
            //prepare the Reshaped Text
            StringBuffer reshapedText=new StringBuffer("");
 
            //Iterate over the Words
            for(int i=0;i<words.length;i++){
 
                //Check if the Word has Arabic Letters
                if(hasArabicLetters(words[i])){
 
                    //Check if the Whole word is Arabic
                    if(isArabicWord(words[i])){
 
                        //Initiate the ArabicReshaper functionality
                        ArabicReshaper arabicReshaper=new ArabicReshaper(words[i],true);
 
                        //Append the Reshaped Arabic Word to the Reshaped Whole Text
                        reshapedText.append(arabicReshaper.getReshapedWord());
                    }else{ //The word has Arabic Letters, but its not an Arabic Word, its a mixed word
 
                        //Extract words from the words (split Arabic, and English)
                        String [] mixedWords=getWordsFromMixedWord(words[i]);
 
                        //iterate over mixed Words
                        for(int j=0;j<mixedWords.length;j++){
 
                            //Initiate the ArabicReshaper functionality
                            ArabicReshaper arabicReshaper=new ArabicReshaper(mixedWords[j],true);
 
                            //Append the Reshaped Arabic Word to the Reshaped Whole Text
                            reshapedText.append(arabicReshaper.getReshapedWord());
                        }
                    }    
                }else{//The word doesn't have any Arabic Letters
 
                    //Just append the word to the whole reshaped Text
                    reshapedText.append(words[i]);
                }
 
                //Append the space to separate between words
                reshapedText.append(" ");
            }
 
            //return the final reshaped whole text
            return reshapedText.toString();
    }
    
    public static TextView getArabicEnabledTextView(Context context, TextView targetTextView) {
        //this is a static for testing!
        Typeface face = Typeface.createFromAsset(context.getAssets(), FONTS_LOCATION_PATH);
        targetTextView.setTypeface(face);
        targetTextView.setGravity(Gravity.RIGHT);
        return targetTextView;
    }
}
 

 


Or you could download the whole project here…


All the best…


image Android Developer in the Making…

Comments

  1. FYI, Honeycomb has already supporting UTF-8 that means Arabic also...

    ReplyDelete
  2. Hello ,

    where can I find something to install on my Android phone to remedy the problem of disconnected letters(HTC Desire S).
    It seems that there’s neither anything ready here http://bar.amr-gawish.com/ !
    I’m not a developer and don’t know how to use the *.java file for my smartphone.

    Could you give me a hint?

    Thanks.

    ReplyDelete
  3. not able to see the connected words like َالَ هَـٰذَا رَحْمَةٌ مِّن رَّبِّي

    ReplyDelete
  4. This library does not support diacriticT

    ReplyDelete
  5. hi,
    thx a lot for this tutorial.
    but I have a question : how did you get this "\uFEB3\uFE92\uFE98\uFE94", what does it represent?
    thank you.

    ReplyDelete
  6. Salam ,
    how we can concatenate arabic letters and english numbers ?? excuse my english .
    thank you

    ReplyDelete

Post a Comment

Popular posts from this blog

Several English proverbs and the Malay pair

Or you could download here for the Malay proverbs app – https://play.google.com/store/apps/details?id=net.kerul.peribahasa English proverbs and the Malay pair Corpus Reference: Amir Muslim, 2009. Peribahasa dan ungkapan Inggeris-Melayu. DBP, Kuala Lumpur http://books.google.com.my/books/about/Peribahasa_dan_ungkapan_Inggeris_Melayu.html?id=bgwwQwAACAAJ CTRL+F to search Proverbs in English Definition in English Similar Malay Proverbs Definition in Malay 1 Where there is a country, there are people. A country must have people. Ada air adalah ikan. Ada negeri adalah rakyatnya. 2 Dry bread at home is better than roast meat home's the best hujan emas di negeri orang,hujan batu di negeri sendiri Betapa baik pun tempat orang, baik lagi tempat sendiri. 3 There's no accounting for tastes We can't assume that every people have a same feel Kepala sama hitam hati lain-lain. Dalam kehidupan ini, setiap insan berbeza cara, kesukaan, perangai, tabia

Contact Us at blog.kerul.net

Powered by EMF HTML Contact Form

The Challenges of Handling Proverbs in Malay-English Machine Translation – a research paper

*This paper was presented in the 14th International Conference on Translation 2013 ( http://ppa14atf.usm.my/ ). 27 – 29 August 2013, Universiti Sains Malaysia, Penang. The PDF version is here: www.scribd.com/doc/163669571/Khirulnizam-The-Challenges-of-Automated-Detection-and-Translation-of-Malay-Proverb The test data is here: http://www.scribd.com/doc/163669588/Test-Data-for-the-Research-Paper-the-Challenges-of-Handling-Proverbs-in-Malay-English-Machine-Translation Khirulnizam Abd Rahman, Faculty of Information Science & Technology, KUIS Abstract: Proverb is a unique feature of Malay language in which a message or advice is not communicated indirectly through metaphoric phrases. However, the use of proverb will cause confusion or misinterpretation if one does not familiar with the phrases since they cannot be translated literally. This paper will discuss the process of automated filtering of Malay proverb in Malay text. The next process is translation. In machine translatio

Online database thru JSON in Android Studio

The tutorial is about how to connect Android apps and online database using the JSON formatted data interchange. The server facilities and JSON encoded data has been explained in the previous tutorials; ( Android and JSON Insert , Android and JSON Search ). The overview concept of JSON data inter change. JSON formatted data sample First we look at our database structure for this project. Part A: The online database The table is training, and this is the structure. There is a PHP script that generate a JSON encoded data from the above table. The PHP script to generate JSON formatted data; <?php //search.php /* * Following code will search training based on keywords */ // array for JSON response $response = array (); // include connect class require_once __DIR__ . '/connect.php' ; // connecting to db $db = new DB_CONNECT(); $keyword = $_GET [ "keyword" ]; // get idioms based on keyword //using LIKE $result =

Submit your blog address here

Create your own blog and send the address by submitting the comment of this article. Make sure to provide your full name, matrix and URL address of your blog. Refer to the picture below. Manual on developing a blog using blogger.com and AdSense, download here … Download Windows Live Writer (a superb offline blog post editor)