2012-11-09 15 views
7

Pracuję nad projektem w Unity, który używa Assembly C#. Próbuję uzyskać specjalną postać, taką jak é, ale w konsoli po prostu wyświetla się pusta postać: "". Na przykład tłumaczenie "Jak się masz?" Powinien zwrócić "Cómo Estás?", Ale zwraca "Cmo Ests". Wstawiłem ciąg zwrotny "Cmo Ests" w tablicy znaków i zdałem sobie sprawę, że jest to pusta, nie pusta litera. Używam Encoding.UTF8, a kiedy zrobić:Jak uzyskać dane wyłączone z postaci

char ch = '\u00e9'; 
print (ch); 

będzie drukować „E”. Próbowałem się bajty od danego łańcucha przy użyciu: „Jak się masz”

byte[] utf8bytes = System.Text.Encoding.UTF8.GetBytes(temp); 

Podczas tłumaczenia, zwróci ciąg bajtów, ale dla znaków specjalnych, takich jak e, pojawia się szereg bajty 239, 191, 189, które są znakami zastępującymi.

Jakiego rodzaju informacji potrzebuję odzyskać od bohaterów, aby dokładnie określić, jaki to jest znak? Czy muszę coś zrobić z informacjami, które daje mi Google, czy jest to coś innego? Potrzebuję ogólnego przypadku, który mogę umieścić w moim programie i będzie pracował dla dowolnego ciągu wejściowego. Jeśli ktokolwiek może pomóc, byłoby to bardzo cenne.

Oto kod, który jest wymieniony:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using UnityEngine; 
using System.Collections; 
using System.Net; 
using HtmlAgilityPack; 


public class Dictionary{ 
string[] formatParams; 
HtmlDocument doc; 
string returnString; 
char[] letters; 
public char[] charString; 
public Dictionary(){ 
    formatParams = new string[2]; 
    doc = new HtmlDocument(); 
    returnString = ""; 
} 

public string Translate(String input, String languagePair, Encoding encoding) 
    { 
     formatParams[0]= input; 
     formatParams[1]= languagePair; 
     string url = String.Format("http://www.google.com/translate_t?hl=en&ie=UTF8&text={0}&langpair={1}", formatParams); 

     string result = String.Empty; 

     using (WebClient webClient = new WebClient()) 
     { 
      webClient.Encoding = encoding; 
      result = webClient.DownloadString(url); 
     }  
     doc.LoadHtml(result); 
     input = alter (input); 
     string temp = doc.DocumentNode.SelectSingleNode("//span[@title='"+input+"']").InnerText; 
     charString = temp.ToCharArray(); 
     return temp; 
    } 
// Use this for initialization 
void Start() { 

} 
string alter(string inputString){ 
    returnString = ""; 
    letters = inputString.ToCharArray(); 
    for(int i=0; i<inputString.Length;i++){ 
     if(letters[i]=='\''){ 
      returnString = returnString + "&#39;"; 
     }else{ 
      returnString = returnString + letters[i]; 
     } 
    } 
    return returnString; 
} 
} 
+0

Powinieneś dołączyć kod, który generuje odpowiedź. –

+0

Nie widzę problemu, szczerze. W twoim pytaniu widzę, że dostajesz dokładnie to, o co prosisz. Jeśli poprosisz o bajty w formacie UTF8, otrzymasz bajty w formacie UTF8. 239, 191, 189 to kodowanie UTF8 dla twojej pojedynczej postaci Unicode. Jeśli chcesz przetłumaczyć z utf8 na unicode, zrób to: http://stackoverflow.com/questions/11293994/how-to-convert-a-utf-8-tring-into-unicode – plinth

+0

Co robi twój 'print() 'Metoda robi? Jeśli próbujesz traktować bajty UTF8 jako znaki, będziesz mieć problemy. Znaki UTF8 mogą mieć więcej niż 1 bajt długości. –

Odpowiedz

0

rzeczywiście dość dużo mieć. Wystarczy wstawić zakodowaną literę za pomocą \ ui to działa.

string mystr = "C\u00f3mo Est\u00e1s?"; 
+0

Dziękuję, ale dotyczy to jednego przypadku. Potrzebuję ogólnego rozwiązania. –

0

nie wiem zbyt wiele o API GoogleTranslate, ale moja pierwsza myśl to, że masz problem normalizacji Unicode.

Spójrz na System.String.Normalize() i jego znajomych.

Unikod jest bardzo skomplikowany, więc uproście go! Wiele symboli może być reprezentowanych na różne sposoby w Unicode, to znaczy: "é" może być reprezentowane jako "é" (jeden znak) lub jako "e" + "znak akcentujący" (dwa znaki) lub, w zależności od tego, co przychodzi z powrotem z API, coś zupełnie innego.

Funkcja Normalize przekształci ciąg znaków w tekst o tym samym znaczeniu tekstowym, ale potencjalnie innej wartości binarnej, która może rozwiązać problem z wydrukiem.

1

Może powinieneś użyć innego API/URL. poniżej Funkcja ta korzysta z innego adresu URL, która zwraca dane JSON i wydaje się lepiej pracować:

public static string Translate(string input, string fromLanguage, string toLanguage) 
    { 
     using (WebClient webClient = new WebClient()) 
     { 
      string url = string.Format("http://translate.google.com/translate_a/t?client=j&text={0}&sl={1}&tl={2}", Uri.EscapeUriString(input), fromLanguage, toLanguage); 
      string result = webClient.DownloadString(url); 

      // I used JavaScriptSerializer but another JSON parser would work 
      JavaScriptSerializer serializer = new JavaScriptSerializer(); 
      Dictionary<string, object> dic = (Dictionary<string, object>)serializer.DeserializeObject(result); 
      Dictionary<string, object> sentences = (Dictionary<string, object>)((object[])dic["sentences"])[0]; 
      return (string)sentences["trans"]; 
     } 
    } 

Jeśli uruchomię to w aplikacji konsoli:

Console.WriteLine(Translate("How are you?", "en", "es")); 

będzie wyświetlać

¿Cómo estás? 
+0

Próbując umieścić to w programie, mówi, że brakuje przestrzeni nazw. Próbowałem "using System.web;" ale nadal mówi, że brakuje przestrzeni nazw. Jakiego obszaru nazw muszę użyć, aby to działało? –

+0

Musisz dodać odniesienie do zestawu do System.Web.Extensions –

+0

@CameronBarge Wprowadziłem kilka poprawek do posta Simona (są one recenzowane), ale ogólnie musisz uwzględnić 'System.Web. Zespoły rozszerzeń (np. W "odniesieniach") i mają "zastosowania" dla "System.Net" i "System.Web.Script.Serialization". – flindeberg

0

Miałem ten sam problem z pracą nad jednym z moich projektów [Tłumaczenie lokalizacji zasobów językowych]

I w jak robi to samo i używa ... System.Text.Encoding.UTF8.GetBytes() i z powodu kodowania utf8 otrzymywał specjalne znaki, takie jak Twój np. 239, 191, 189 w ciągu wynikowym.

proszę spojrzeć na moje rozwiązanie ...mam nadzieję, że to pomoże.

Nie używaj kodowania w ogóle tłumaczenie Google zwróci poprawne jak á jak sam w ciągu znaków. zrobić jakiś ciąg manipulacji i odczytać ciąg, jak to jest ...

Generic Rozwiązanie [prace dla każdego tłumaczy który google wspomagający]

try 
{ 
    //Don't use UtF Encoding 
    // use default webclient encoding 

    var url = String.Format("http://www.google.com/translate_t?hl=en&text={0}&langpair={1}", "►" + txtNewResourceValue.Text.Trim() + "◄", "en|" + item.Text.Substring(0, 2));      

    var webClient = new WebClient(); 
    string result = webClient.DownloadString(url); //get all data from google translate in UTF8 coding.. 

     int start = result.IndexOf("id=result_box"); 
     int end = result.IndexOf("id=spell-place-holder"); 
     int length = end - start; 
     result = result.Substring(start, length); 
     result = reverseString(result); 

     start = result.IndexOf(";8669#&");//◄ 
     end = result.IndexOf(";8569#&"); //► 
     length = end - start; 

     result = result.Substring(start +7 , length - 8); 
     objDic2.Text = reverseString(result); 

     //hard code substring; finding the correct translation within the string. 
     dictList.Add(objDic2); 
} 
catch (Exception ex) 
{ 
    lblMessages.InnerHtml = "<strong>Google translate exception occured no resource saved..." + ex.Message + "</strong>"; 
       error = true; 
} 

public static string reverseString(string s) 
{ 
    char[] arr = s.ToCharArray(); 
    Array.Reverse(arr); 
    return new string(arr); 

} 

jak widać z kodu bez kodowania został wykonałem i wysyłam 2 specjalne kluczowe znaki jako "►" + txtNewResourceValue.Text.Trim() + "◄" w celu określenia początku i końca tłumaczenia zwrotnego z google.

Również sprawdziłem, czy moje narzędzie do narzędzi językowych otrzymuję komunikat "Cómo Estás?" podczas wysyłania Jak Ci pomocną ... :)

poważaniem [Shaz]

---------------------- ----- Edytowane -------------------------

public string Przekłada (wejście String, String languagePair) {

try 
    { 


     //Don't use UtF Encoding 
     // use default webclient encoding 
     //input  [string to translate] 
     //Languagepair [eg|es] 

     var url = String.Format("http://www.google.com/translate_t?hl=en&text={0}&langpair={1}", "►" + input.Trim() + "◄", languagePair); 

     var webClient = new WebClient(); 
     string result = webClient.DownloadString(url); //get all data from google translate 

     int start = result.IndexOf("id=result_box"); 
     int end = result.IndexOf("id=spell-place-holder"); 
     int length = end - start; 
     result = result.Substring(start, length); 
     result = reverseString(result); 

     start = result.IndexOf(";8669#&");//◄ 
     end = result.IndexOf(";8569#&"); //► 
     length = end - start; 

     result = result.Substring(start + 7, length - 8); 

     //return transalted string 
     return reverseString(result); 


    } 
    catch (Exception ex) 
    { 
     return "Google translate exception occured no resource saved..." + ex.Message"; 

    } 
} 
+0

Dziękuję za odpowiedź. Czy mógłbyś dać mi trochę więcej informacji na temat tego, gdzie powinno to dotyczyć mojego kodu, np. nazwa i parametry metody. Każda pomoc będzie doceniona. –

+0

@Cameron, proszę spojrzeć na nowy, zredagowany kod, który powinien zadziałać ... na każde pytanie daj mi znać ... – Shaz

0

Jest kilka problemów z twoim podejściem. Przede wszystkim kodowanie UTF8 jest kodowaniem wielobajtowym. Oznacza to, że jeśli użyjesz dowolnego znaku spoza zestawu ASCII (o kodzie znaku> 127), otrzymasz serię znaków specjalnych, które wskazują systemowi, że jest to znak Unicode. Tak więc twoja sekwencja 239, 191, 189 wskazuje na pojedynczy znak, który nie jest znakiem ASCII. Jeśli używasz UTF16, otrzymujesz kodowanie o stałym rozmiarze (kodowanie 2-bajtowe), które faktycznie zamienia znak na niepodpisany skrót (0-65535).

Typ znaku C# jest typem dwubajtowym, więc w rzeczywistości jest to niepodpisany skrót. Kontrastuje to z innymi językami, takimi jak C/C++, gdzie typ znaku jest typem 1-bajtowym.

Tak więc w twoim przypadku, chyba że naprawdę potrzebujesz używać tablic bajtowych [], powinieneś użyć tablic char []. Lub jeśli chcesz zakodować znaki, aby mogły być użyte w HTML, możesz po prostu powtórzyć kolejne znaki i sprawdzić, czy kod znaku jest> 128, a następnie zastąpić go kodem postaci &hex;.

Powiązane problemy