2012-04-19 211 views
24

曾經有一些服務使用谷歌翻譯API V1自動翻譯.po文件。自動翻譯.po文件?

谷歌已經停止了他們的V1 API,而用V2他們收取了20美元的1000,000字。

我已經搜索,但無法找到任何提供翻譯V2版本的工具。你會期望有人更新他們的工具,並收取20,000美元的2美元的話費,並獲得很好的利潤。

是否有任何付費或免費的工具可以自動翻譯.po文件?

+1

谷歌不允許你重新出售其支付的翻譯,根據其服務條款,所以沒有人能夠做什麼你建議... – daveagp 2012-08-31 00:21:21

回答

-3

你甚至沒有嘗試的主文件夾? http://www.po-auto-translator.tk/工作得很好,我只是下載了軟件。

+2

這個網站也是死的 – Alberto 2013-11-25 11:15:12

+0

以上的副本 – Sam 2014-08-18 05:55:29

+0

網站沒有工作 – OzzyCzech 2015-04-28 21:07:21

1

見我的免費PHP工具Potrans,其中使用谷歌翻譯API從這裏回購

下載翻譯PO文件:https://github.com/OzzyCzech/potrans

+0

太棒了!有%s和%d個變量存在一些缺陷,但總而言之,這很好。謝謝 – JohnWolf 2015-02-14 09:48:39

0

隨意編輯這篇文章進行更正或更好的錯誤處理。我不是.po文件格式的專家,但我認爲這將適用於我的angular-gettext需求。我認爲我使用的唯一外部庫是Newtonsoft的Json.NET。我不屬於Frengly。它出現在谷歌上。如果您需要每3秒鐘翻譯一次以上,我建議您使用其他翻譯API。


輸入文件:template.pot

msgid "" 
msgstr "" 
"Content-Type: text/plain; charset=UTF-8\n" 
"Content-Transfer-Encoding: 8bit\n" 

#: Comment 
msgid "You do not have permission to view this application" 
msgstr "" 

msgid "You have permission to view this application" 
msgstr "" 

輸入命令:> program.exe template.pot en es_VE fr_FR


輸出文件1:en.cache.json 這是創建所以,無論翻譯uti你使用的禮物不必一遍又一遍地被擊中。

{ 
    "es_VE": { 
    "You do not have permission to view this application": "Tu no la habana permiso que vista este aplicación", 
    "You have permission to view this application": "Tu tienes permiso que vista este aplicación" 
    }, 
    "fr_FR": { 
    "You do not have permission to view this application": "Vous le faites pas as autorisation a vue cette une demande", 
    "You have permission to view this application": "Tuas autorisation a vue cette une demande" 
    } 
} 

輸出文件2:es_VE.po

msgid "" 
msgstr "" 
"Content-Type: text/plain; charset=UTF-8\n" 
"Content-Transfer-Encoding: 8bit\n" 

#: Comment 
msgid "You do not have permission to view this application" 
msgstr "Tu no la habana permiso que vista este aplicación" 

msgid "You have permission to view this application" 
msgstr "Tu tienes permiso que vista este aplicación" 

輸出文件3:fr_FR目錄。PO

msgid "" 
msgstr "" 
"Content-Type: text/plain; charset=UTF-8\n" 
"Content-Transfer-Encoding: 8bit\n" 

#: Comment 
msgid "You do not have permission to view this application" 
msgstr "Vous le faites pas as autorisation a vue cette une demande" 

msgid "You have permission to view this application" 
msgstr "Tuas autorisation a vue cette une demande" 

來源

public interface ICache 
{ 
    void Add(string language, IEntry entry); 

    IEntry Get(string language, string id); 

    string GetSerialized(); 
} 

public class JsonCache : ICache 
{ 
    private Dictionary<string, Dictionary<string, string>> _cache; 

    public JsonCache(string json) 
    { 
     this._cache = 
      json == null ? 
      new Dictionary<string, Dictionary<string, string>>() : 
      JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, string>>>(json); 
    } 

    public void Add(string language, IEntry entry) 
    { 
     if (!this._cache.ContainsKey(language)) 
     { 
      this._cache.Add(language, new Dictionary<string, string>()); 
     } 

     var languageCache = this._cache[language]; 

     languageCache.Add(entry.Id, entry.Value); 
    } 

    public IEntry Get(string language, string id) 
    { 
     if (!this._cache.ContainsKey(language)) 
     { 
      return null; 
     } 

     var languageCache = this._cache[language]; 

     Entry result = null; 

     if (languageCache.ContainsKey(id)) 
     { 
      result = new Entry(); 
      result.Id = id; 
      result.Value = languageCache[id]; 
     } 

     return result; 
    } 

    public string GetSerialized() 
    { 
     return JsonConvert.SerializeObject(this._cache, Formatting.Indented); 
    } 
} 

public interface IReader : IDisposable 
{ 
    IEntry Read(); 
} 

public class PoReader : IReader 
{ 
    private StreamReader _reader; 

    public PoReader(string fileName) 
    { 
     this._reader = new StreamReader(fileName); 
    } 

    public void Dispose() 
    { 
     if (this._reader != null) 
     { 
      this._reader.Dispose(); 
     } 
    } 

    public IEntry Read() 
    { 
     var entry = new Entry(); 

     while (entry.Id == null || entry.Value == null) 
     { 
      var line = this._reader.ReadLine(); 
      if (line == null) 
      { 
       return null; 
      } 

      if (line.StartsWith(Constants.StartComment)) 
      { 
       entry.Comment = line.Substring(Constants.StartComment.Length); 
      } 
      else if (line.StartsWith(Constants.StartId)) 
      { 
       entry.Id = line.Substring(Constants.StartId.Length); 
       // Remove the double quotes. 
       entry.Id = entry.Id.Substring(1, entry.Id.Length - 2); 
      } 
      else if (line.StartsWith(Constants.StartValue)) 
      { 
       entry.Value = line.Substring(Constants.StartValue.Length); 
       // Remove the double quotes. 
       entry.Value = entry.Value.Substring(1, entry.Value.Length - 2); 
      } 
     } 

     // Skip the first entry 
     if (entry.Id.Length == 0) 
     { 
      return this.Read(); 
     } 

     return entry; 
    } 
} 

public class CachedTranslator : ITranslator 
{ 
    private ITranslator _translator; 
    private ICache _cache; 

    public CachedTranslator(ICache cache, ITranslator translator) 
    { 
     this._translator = translator; 
     this._cache = cache; 
    } 

    public IEntry Translate(string language, IEntry entry) 
    { 
     var result = this._cache.Get(language, entry.Id); 
     if (result == null) 
     { 
      result = this._translator.Translate(language, entry); 
      this._cache.Add(language, result); 
     } 
     else 
     { 
      // We don't want to use the cached comment. 
      var clone = new Entry(); 

      clone.Comment = entry.Comment; 
      clone.Value = result.Value; 
      clone.Id = result.Id; 

      result = clone; 
     } 
     return result; 
    } 
} 

public class FrenglyTranslator : ITranslator 
{ 
    private string _password; 
    private string _email; 
    private string _inLanguage; 

    public FrenglyTranslator(string email, string password, string inLanguage) 
    { 
     this._email = email; 
     this._password = password; 
     this._inLanguage = inLanguage; 
    } 

    public IEntry Translate(string language, IEntry entry) 
    { 
     var url = string.Format("http://syslang.com?src={4}&dest={0}&text={1}&email={2}&password={3}&outformat=json", 
      language.Substring(0, 2), 
      entry.Id, 
      this._email, 
      this._password, 
      this._inLanguage); 

     var result = new Entry(); 
     result.Id = entry.Id; 
     result.Comment = entry.Comment; 

     using (var client = new HttpClient()) 
     { 
      var clientResult = client.GetStringAsync(url).Result; 
      var jo = (JObject)JsonConvert.DeserializeObject(clientResult);    
      result.Value = jo.Property("translation").Value.Value<string>(); 
     } 

     // Must wait 3 seconds between calls. 
     Thread.Sleep(3001); 

     return result; 
    } 
} 

public interface ITranslator 
{ 
    IEntry Translate(string language, IEntry entry); 
} 

public interface IWriter : IDisposable 
{ 
    void Write(IEntry entry); 
} 

public class PoWriter : IWriter 
{ 
    private StreamWriter _writer; 

    public PoWriter(string fileName) 
    { 
     this._writer = new StreamWriter(fileName); 

     var header = @"msgid """" 
msgstr """" 
""Content-Type: text/plain; charset=UTF-8\n"" 
""Content-Transfer-Encoding: 8bit\n"""; 

     this._writer.WriteLine(header); 
    } 

    public void Write(IEntry entry) 
    { 
     this._writer.WriteLine(); 

     if (entry.Comment != null && entry.Comment.Length > 0) 
     { 
      this._writer.WriteLine(Constants.StartComment + entry.Comment); 
     } 

     this._writer.WriteLine(string.Format("{0}\"{1}\"", Constants.StartId, entry.Id)); 
     this._writer.WriteLine(string.Format("{0}\"{1}\"", Constants.StartValue, entry.Value)); 
    } 

    public void Dispose() 
    { 
     if (this._writer != null) 
     { 
      this._writer.Dispose(); 
     } 
    } 
} 

public static class Constants 
{ 
    public const string StartComment = "#: "; 
    public const string StartId = "msgid "; 
    public const string StartValue = "msgstr "; 
} 

public class Entry : IEntry 
{ 
    public string Comment { get; set; } 

    public string Value { get; set; } 

    public string Id { get; set; } 
} 

public interface IEntry 
{ 
    string Comment { get; } 

    string Value { get; } 

    string Id { get; } 
} 

class Program 
{ 
    private const string cacheFileNameSuffix = ".cache.json"; 
    private const string frenglyEmail = "[email protected]"; 
    private const string frenglyPassword = "YourPassword"; 

    static void Main(string[] args) 
    { 
     // 
     // INITIALIZE 
     // 
     var inFileName = args[0]; 
     var inLanguage = args[1]; 
     var outLanguages = args.Skip(2); 

     // ICache 
     var cacheFileName = inLanguage + cacheFileNameSuffix; 
     var json = File.Exists(cacheFileName) ? File.ReadAllText(cacheFileName) : null; 
     ICache cache = new JsonCache(json); 

     // ITranslator 
     ITranslator translator = new FrenglyTranslator(frenglyEmail, frenglyPassword, inLanguage); 
     ITranslator cachedTranslator = new CachedTranslator(cache, translator); 

     // IWriters 
     var writers = new Dictionary<string, IWriter>(); 
     foreach (var language in outLanguages) 
     { 
      writers.Add(language, new PoWriter(language + ".po")); 
     } 

     try 
     { 
      using (IReader reader = new PoReader(inFileName)) 
      { 
       // 
       // RUN 
       // 
       IEntry entry = null; 
       while (true) 
       { 
        entry = reader.Read(); 
        if (entry == null) 
        { 
         break; 
        } 

        foreach (var kv in writers) 
        { 
         var translated = cachedTranslator.Translate(kv.Key, entry); 
         kv.Value.Write(translated); 
        } 
       } 
      } 
     } 
     finally 
     { 
      // Store the cache. 
      File.WriteAllText(cacheFileName, cache.GetSerialized()); 

      // 
      // CLEANUP 
      // 

      // Dispose of the writers. 
      foreach (var writer in writers.Values) 
      { 
       if (writer != null) 
       { 
        writer.Dispose(); 
       } 
      } 
     } 
    } 
} 
相關問題