如何使用Java将印地语文本在印地语和拉丁字符之间进行音译?

3
如何使用Java将用英文字母书写的印地语词义转换为印地语?
例如:
输入文本:anil NE lath marke apko Ganga me hi Fenk diya。
输出文本:अनिल ने लात मारके आपको गंगा में ही फेंक दिया。
如何使用Java或任何Java API进行转换?
我发现了一个名为Jitter的API,但是出现了错误。
Source is: inko
Input is: a2b45xdsfsdf
Output is: 
Matches is: 0
Exception in thread "main" org.jtr.transliterate.CharacterParseException: No valid delimiter found for start of expression
    at org.jtr.transliterate.Perl5Parser.parsePerlString(Perl5Parser.java:133)

源代码是指

/*
 * Copyright (c) 2001-2005, Nicholas Cull
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 *  * Neither the name "jtr" nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.jtr.transliterate;

/**
 * A utility class for providing Perl 5 syntactic sugar on top of the
 * {@link CharacterParser} class. This parses Perl-style transliteration strings
 * into a form suitable for <code>CharacterParser</code>. For instance, the
 * string <code>"tr/a-zA-Z/0-9a-zA-Z/cd"</code> is parsed into two strings
 * <code>"a-zA-Z"</code>, <code>"0-9a-zA-Z"</code>, and the flags
 * <code>COMPLEMENT_MASK | DELETE_UNREPLACEABLES_MASK</code>.
 *
 * @author <a href="mailto:run2000@users.sourceforge.net">Nicholas Cull</a>
 * @version $Id: Perl5Parser.java,v 1.3 2005/03/14 06:40:18 run2000 Exp $
 * @since 1.1
 */
public final class Perl5Parser {

    /** Initial state of the sequence parser. */
    private static final short INITIAL_STATE = 0;
    /** Sequence parser encountered an escape character. */
    private static final short ESCAPE_STATE = 1;
    /** Sequence parser encountered the delimiter. */
    private static final short DELIMITER_STATE = 2;

    /** Private constructor to indicate this is a static class. */
    private Perl5Parser() {
    }

    /**
     * <p>Parses the given string in Perl syntax and returns a populated
     * {@link CharacterReplacer} object that can be used to perform the
     * specified transliteration.</p>
     *
     * <p>This is a simple factory method that calls the {@link #parsePerlString
     * parsePerlString} method below, creates a new {@link CharacterReplacer}
     * object and populates it with the results.</p>
     *
     * @param source the String to be parsed and compiled
     * @return a new CharacterReplacer ready for transliterations
     * @throws CharacterParseException something went wrong during parsing
     * @throws NullPointerException source is <code>null</code>
     */
    public static CharacterReplacer makeReplacer( String source )
            throws CharacterParseException {

        StringBuffer input = new StringBuffer();
        StringBuffer output = new StringBuffer();
        int flags = 0;
        CharacterReplacer replacer;

        flags = parsePerlString( source, input, output );
        replacer = new CharacterReplacer( input.toString(), output.toString() );
        replacer.setFlags( flags );
        return replacer;
    }

    /**
     * <p>Parses the given Perl-style transliteration string into two parts:</p>
     * <ol>
     * <li>The input character string to be transliterated
     * <li>The replacement character string
     * </ol>
     * <p>These strings can then be fed into the constructors for
     * {@link CharacterReplacer}. It also returns any flags encountered at the
     * end of the string into a form suitable for CharacterReplacer.</p>
     *
     * @param source the string to be parsed
     * @param input (out) the characters to be transliterated
     * @param output (out) the replacement characters
     * @return any flags parsed at the end of the character sequence
     * @throws CharacterParseException there was a problem parsing the source
     * String
     * @throws NullPointerException source is <code>null</code>
     */
    public static int parsePerlString( String source, StringBuffer input,
            StringBuffer output ) throws CharacterParseException {

        int length = source.length();
        int pos = 0;
        int flags = 0;
        char delimiter;

        if( length < 3 ) {
            throw new CharacterParseException(
                    "Source is too small to be parsed", pos );
        }

        if( input == null || output == null ) {
            throw new CharacterParseException(
                    "String buffers have not been initialized", pos );
        }

        if( source.startsWith( "tr" )) {
            pos = 2;
        } else if( source.startsWith( "y" )) {
            pos = 1;
        }

        delimiter = source.charAt( pos );
        if( delimiter == '-' || delimiter == '\\' ||
                Character.isLetterOrDigit( delimiter )) {
            throw new CharacterParseException(
                    "No valid delimiter found for start of expression", pos );
        }

        pos++;
        pos = parseSequence( source, pos, delimiter, input );

        if( pos == length ) {
            throw new CharacterParseException(
                    "Cannot parse replacement sequence, no character sequence found",
                    pos );
        }

        pos = parseSequence( source, pos, delimiter, output );

        // Parse any flags at the end
        while( pos < length ) {
            char flag = source.charAt( pos );
            switch( flag ) {
                case 'c':
                    flags = flags | CharacterParser.COMPLEMENT_MASK;
                    break;

                case 'd':
                    flags = flags | CharacterParser.DELETE_UNREPLACEABLES_MASK;
                    break;

                case 's':
                    flags = flags | CharacterParser.SQUASH_DUPLICATES_MASK;
                    break;

                default:
                    throw new CharacterParseException(
                            "Unknown flag passed into character parser", pos );
            }
            pos++;
        }
        return flags;
    }

    /**
     * Parse the first or second character sequence and place the parsed result
     * into the given StringBuffer. The source string is scanned from initial
     * position pos until an unescaped delimiter character is found. We use a
     * simple finite state machine to determine when we encounter an escape
     * character or a delimiter.
     *
     * @param source the source String to be scanned
     * @param pos the starting position for the scan
     * @param delimiter the delimiter character to indicate the end of the
     * sequence
     * @param buffer the character buffer to store the parsed result
     * @return the new position of the parser
     * @throws NullPointerException source or buffer are <code>null</code>
     */
    private static int parseSequence( String source, int pos, char delimiter,
                                      StringBuffer buffer ) {
        int length = source.length();
        short state = INITIAL_STATE;
        int startPos = pos;
        char curr = '\0';

        while(( pos < length ) && ( state != DELIMITER_STATE )) {
            curr = source.charAt( pos );
            switch( state ) {
                case INITIAL_STATE:
                    if( curr == '\\' ) {
                        state = ESCAPE_STATE;
                    } else if( curr == delimiter ) {
                        // Copy the current source to the buffer
                        buffer.append( source.substring( startPos, pos ));
                        state = DELIMITER_STATE;
                    }
                    break;

                case ESCAPE_STATE:
                    if( curr == delimiter ) {
                        // Previous character was to escape the delimiter.
                        // Have to add the previous characters to the buffer.
                        buffer.append( source.substring( startPos, pos - 1 ));
                        startPos = pos;
                    }
                    state = INITIAL_STATE;
                    break;
            }
            pos++;
        }

        if( state != DELIMITER_STATE ) {
            buffer.append( source.substring( startPos ));
        }
        return pos;
    }

    /**
     * A simple test case for this class.
     *
     * @param args ignored
     * @throws Exception if an exception is encountered, throw it to the caller
     */
    public static void main( String args[] ) throws Exception {
        String source = "inko";
        String input = "a2b45xdsfsdf";
        String output = "";
        int matches = 0;

        try {
            CharacterReplacer replacer = makeReplacer( source );
            output = replacer.doReplacement( input );
            matches = replacer.getMatches();
        } finally {
            System.out.println( "Source is: " + source );
            System.out.println( "Input is: " + input );
            System.out.println( "Output is: " + output );
            System.out.println( "Matches is: " + matches );
        }
    }
}

at org.jtr.transliterate.Perl5Parser.makeReplacer(Perl5Parser.java:82)
at org.jtr.transliterate.Perl5Parser.main(Perl5Parser.java:240)

你真的想使用一个更好的谷歌翻译版本作为Java API。 - Bharat Sinha
我重新改写了你的问题,因为你的例子实际上并没有展示出“翻译”,而只是展示了“音译”,这两者是有很大区别的! - Joachim Sauer
Google翻译API可以完成此任务,但它可能会将“hello aap kaise ho”翻译成“नमस्ते आप कैसे हो”。请参见http://translate.google.com/#auto|hi|hello%20aap%20kaise%20ho。 - jmj
谷歌提供了REST API,您可以很容易地从Java中使用它。 - jmj
您可以通过向其URI发送HTTP GET请求将文本从一种语言翻译成另一种语言。请求的URI具有以下格式:[https://developers.google.com/translate/v2/using_rest#Translate]. - jmj
显示剩余3条评论
2个回答

1

如果我理解你的意思正确的话,那么你想要能够将印地语文本进行音译(即从一种书写系统转换为另一种)。这通常比翻译(即从一种语言转换为另一种)容易得多。

我不知道有哪个库可以做到这一点,但是这个维基词典页面关于印地语音译可能会帮助你入门。


2
@SoniaGupta:我已经写过“我不知道有哪个库可以做到这一点”。 - Joachim Sauer

0
我看过一个名为hinkhoj的Android词典,它可以在没有网络连接的情况下完成同样的功能。所以在Java中肯定是可行的。
将每个字母或字母组合替换为相应的印地语Unicode码将会起作用。例如,将'ma'替换为'\u092E'。
示例工作程序:
public class EnglishToHindiTranslator {

    static Map<String, String> phoneticMap = new HashMap<String, String>();
    static Map<String, String> maatraMap = new HashMap<String, String>();

    static {
        phoneticMap.put("ma","\u092E");
        phoneticMap.put("ta","\u0924");
        phoneticMap.put("t","\u0924\u094D");
        phoneticMap.put("ra","\u0930");
        maatraMap.put("a","\u093E");
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        String engWord = "maatra";
        engWord = engWord.replaceAll("ma",phoneticMap.get("ma") );
        engWord = engWord.replaceAll("t",phoneticMap.get("t") );
        engWord = engWord.replaceAll("ra",phoneticMap.get("ra") );
        engWord = engWord.replaceAll("a",maatraMap.get("a") );

        System.out.println(new String(engWord.getBytes("UTF-8")));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接