Archive for the 'NSLinguisticTagger' Category

2017/04/11 指定のテキストから言語コードや言語名を取得する

Shane Stanleyによる、指定テキストを識別して言語コードや言語名を取得するAppleScriptです。

割とアラビア語のテキストを判定するのに文字数が必要だったのが意外です。

以前に掲載した「2015/09/10 テキストの言語を推測する」よりも若干(1行ぐらい)短くなっています。

AppleScript名:指定のテキストから言語コードや言語名を取得する
– Created 2017-04-10 by Shane Stanley
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

set str1 to “Ilmatyynyalukseni on täynnä ankeriaita.”
set str2 to “Luftputebåten min er full av ål”
set str3 to “私の名前は長野谷です。”
set str4 to أنشأ فوكوزاوا يوكيتشي (١٨٣٥-١٩٠١) في اكتوبر عام ١٨٥٨ مدرسة للدراسات الهولندية (تحولت بعد ذلك لمدرسة للغة الانكليزية) في ايدو (طوكيو حاليا). يعد فوكوزاوا يوكيتشي من أحد مؤسسي نهضة اليابان الحديثة، فونهتم بمدرستنا بنوع التعليم الذي ينمي القدرات الإبداعية والفنية التي يتطلب توافرها في طلاب الجامعة بحيث لا ينشغل الطلاب باختبار قبول الجامعات ونحترم استقلالية وتفرد كل طالب وذلك في جو دافئ في بيئة طبيعية مليئة بأشجار
set str5 to 게이오 기주쿠는 어디에나 있는 학교의 하나로 만족하지 않습니다. 게이오 기주쿠는 기주쿠(義塾, 의숙)에서 배우는 학생과 교원이 일본의기품의 원천지덕의 모범 되는 것을 목표로 하는 학숙(學塾)입니다. “
set str6 to 庆应义塾不是仅仅满足于成常常到的一般性学校。”

set a1Res to my guessLanguageCodeOf:str1 –>  ”fi”
set a2Res to my guessLanguageCodeOf:str2 –>  ”sv”
set a3Res to my guessLanguageCodeOf:str3 –>  ”ja”
set a4Res to my guessLanguageCodeOf:str4 –>  ”ar”
set a5Res to my guessLanguageCodeOf:str5 –>  ”ko”
set a6Res to my guessLanguageCodeOf:str6 –>  ”zh-Hans”

set b1Res to my guessLanguageOf:str1 –>  ”Finnish”
set b2Res to my guessLanguageOf:str2 –>  ”Swedish”
set b3Res to my guessLanguageOf:str3 –>  ”Japanese”
set b4Res to my guessLanguageOf:str4 –>  ”Arabic”
set b5Res to my guessLanguageOf:str5 –>  ”Korean”
set b6Res to my guessLanguageOf:str6 –>  ”Chinese”

on guessLanguageOf:theString
  set theTagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:{current application’s NSLinguisticTagSchemeLanguage} options:0
  
theTagger’s setString:theString
  
set languageID to theTagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value)
  
return ((current application’s NSLocale’s localeWithLocaleIdentifier:“en”)’s localizedStringForLanguageCode:languageID) as text
end guessLanguageOf:

on guessLanguageCodeOf:theString
  set theTagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:{current application’s NSLinguisticTagSchemeLanguage} options:0
  
theTagger’s setString:theString
  
set languageID to theTagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value)
  
return languageID as text
end guessLanguageCodeOf:

★Click Here to Open This Script 

2015/10/03 文字エンコーディングを自動判別して日本語テキストファイル読み込み v1.2.1

Cocoaの機能と人間の知恵を総動員して未知の文字エンコーディングのテキストファイルに対して、文字エンコーディングを推測して「日本語の」テキストとして読み取るAppleScriptです。

未知といっておきながら、対象としているのは「UTF-8」「シフトJIS」「EUC」「ISO-2022JP」「UTF16(BOMなし)」、「UTF16(無表記)」「UTF-16BE」「UTF-16LE」です。メインフレームのEBCDICコードとかは想定していませんごめんなさいごめんなさい(誰に謝る?)。

「UTF-8」「シフトJIS」「EUC」「ISO-2022JP」については、判断方法が割と確立しているので安全に判定と読み取りが行えています。

問題は「それ以外の皆さん」(とくに「UTF16(無表記)」「UTF-16BE」「UTF-16LE」)です。

それぞれについて、文字コードチェックを総当たりで行い、問題がないものを採用するというのが順当なところですが、「問題があると判定されつつも問題がないパターン」「問題がないと判定されつつも問題があるパターン」のてんこもり。困ったところです。

解決策1:NSLinguisticTaggerに聞く

テキストを渡すと言語を判定してくれるNSLinguisticTaggerに聞いてみました。文字化けしていたら日本語として判定できないだろうという考えです。

サンプルのテキストはテクニカル系の記事(PC Watchの記事、SJISで11KB)と、ザ・近代文学ともいえる「坊ちゃん」(SJISで210KB)です。「坊ちゃん」のテキストを喰わせて「日本語」と判定できなかったらかなり問題ですが、そこは大丈夫でした。問題はアルファベットや数字が多いテクニカル系の記事で、NSLinguisticTaggerでは日本語として判定されませんでした(残念!)。

解決策2:行数と単語数をカウント

今度は、AppleScriptが持っている(最低限の)形態素解析能力を利用します(固有名詞を「連絡先」アプリや漢字変換辞書から引いてこないのがダメ)。OS X 10.6から、それ以前の「文字種類が変わったところで単語とみなす」というアホな単語切り分けをあらため、少しはマシな単語切り分けをするようになってきました(Mecabの機能を利用しているもよう。辞書固定だけど)

文字化けして謎の文字ばかり出てきた場合には、ほぼ1文字=1単語ぐらいに認識されるはずなので、経験的に言って「行数が1行の場合には文字化けしている」「単語数が多すぎる場合には文字化けしている」と言っても過言ではないでしょう。

これらを、文字エンコードを多数決的に「UTF16(無表記)」「UTF-16BE」「UTF-16LE」「UTF16(BOMなし)」の処理結果を寄せ集めて判定するようにしてみました。

その結果がこちらです。

table1.png

v1.1の弱点を埋めようとして改良したv1.2において、逆に認識文字コードが減ってしまいました。ただし、認識順を調整するのではなしに「UTF16(無表記)」「UTF-16BE」「UTF-16LE」を総当たりでチェックして、その結果を評価すれば全部判定できるのでは? という気づきにつながりました(失敗は成功のマザー)。

手元に用意したサンプルの範囲では、ヒット率が100%。ぜひ多くの方々に使っていただいて、「ダメだった」パターンを集めてフィードバックしたいところです。こうして強化していけば、「文字コード判定のためだけにわざわざテキストエディタを操作する」とかいうアホな状況を回避できるものと思われます。

一応、El Capitan的にはEnumのBridgeが利くようになって、NSShiftJISStringEncodingといった定数をそのまま「current application’s NSShiftJISStringEncoding」などと書いています。ただ、数字の桁数がやたらと多いEnumは変数に入れたりした瞬間に指数表示になる(アホすぎる!)ので、変数にも代入できずに直接書いています。

AppleScript名:文字エンコーディングを自動判別してファイル読み込み v1.2.1
– Created 2014-12-28 by Takaaki Naganoya
– Modified 2014-12-29 by Shane Stanley
– Modified 2015-10-03 by Takaaki Naganoya
use AppleScript version “2.5″
use scripting additions
use framework “Foundation”

set aPath to POSIX path of (choose file)
set aRes to readJapanesTextFileWithGuessingEncoding(aPath) of me

–Read Japanese text with detecting its text encoding
on readJapanesTextFileWithGuessingEncoding(aPOSIXpath as string)
  
  
–ISO2022JP check
  
set aNSData to current application’s NSData’s dataWithContentsOfFile:aPOSIXpath
  
set aDataLength to aNSData’s |length|()
  
if aDataLength > 1024 then set aDataLength to 1024
  
  
–0×1B check
  
set anNSString to current application’s NSString’s stringWithString:(character id 27) – 0×1B
  
set theData to anNSString’s dataUsingEncoding:(current application’s NSUTF8StringEncoding)
  
set theRange to aNSData’s rangeOfData:theData options:0 range:(current application’s NSMakeRange(0, aDataLength))
  
  
–found 0×1B in aNSData
  
if |length| of theRange = 1 and location of theRange < aDataLength then
    set aStr to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSISO2022JPStringEncoding)) –21
    
if aStr is not equal to missing value then return (aStr as text) – ISO2022JP
  end if
  
  
–EUC
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSJapaneseEUCStringEncoding))
  
if resValue is not equal to missing value then return (resValue as text)
  
–UTF-8
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF8StringEncoding))
  
if resValue is not equal to missing value then return (resValue as text)
  
–SHift JIS
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSShiftJISStringEncoding))
  
if resValue is not equal to missing value then return (resValue as text)
  
  
  
–UTF-16BE/LE/無印Unicodeは多数決を取る
  
set resValue1 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF16BigEndianStringEncoding)) as text
  
set sample1 to getTextSample(resValue1) of me
  
set lang1 to specifyLanguageOfText(sample1) of me
  
set para1 to length of (paragraphs of sample1)
  
set words1 to length of (words of sample1)
  
  
set resValue2 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUTF16LittleEndianStringEncoding)) as text
  
set sample2 to getTextSample(resValue2) of me
  
set lang2 to specifyLanguageOfText(sample2) of me
  
set para2 to length of (paragraphs of sample2)
  
set words2 to length of (words of sample2)
  
  
set resValue3 to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSUnicodeStringEncoding)) as text
  
set sample3 to getTextSample(resValue3) of me
  
set lang3 to specifyLanguageOfText(sample3) of me
  
set para3 to length of (paragraphs of sample3)
  
set words3 to length of (words of sample3)
  
  
–文字および文法的に見て「日本語」ならそれを返す
  
if lang1 = “ja” then return resValue1
  
if lang2 = “ja” then return resValue2
  
if lang3 = “ja” then return resValue2
  
  
  
–文字化けしたときには、日本語の「Word」として認識されづらく、Paragraphも少ない(1とか)なので条件で除外する
  
if para1 is not equal to 1 then
    if (words1 words2) or (words1 words3) then
      return resValue1
    end if
  end if
  
  
if para2 is not equal to 1 then
    if (words2 words1) or (words2 words3) then
      return resValue2
    end if
  end if
  
  
if para3 is not equal to 1 then
    if (words3 words1) or (words3 words2) then
      return resValue3
    end if
  end if
  
  
  
  
–おまけ(未確認)
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1251StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1252StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1253StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1254StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
set resValue to (current application’s NSString’s alloc()’s initWithData:aNSData encoding:(current application’s NSWindowsCP1250StringEncoding))
  
if resValue is not equal to missing value then return resValue
  
  
return false
  
end readJapanesTextFileWithGuessingEncoding

on specifyLanguageOfText(aStr)
  set aNSstring to current application’s NSString’s stringWithString:aStr
  
set tagSchemes to current application’s NSArray’s arrayWithObjects:(current application’s NSLinguisticTagSchemeLanguage)
  
set tagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:tagSchemes options:0
  
tagger’s setString:aNSstring
  
set aLanguage to tagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value)
  
return aLanguage as text
end specifyLanguageOfText

on getTextSample(aText)
  set aLen to length of aText
  
if aLen < 1024 then
    set bLen to aLen
  else
    set bLen to 1024
  end if
  
return (text 1 thru bLen of aText)
end getTextSample

★Click Here to Open This Script 

2015/09/11 与えられたテキストの言語を自動判別して対応する言語のTTS Voiceで読み上げ

Cocoaの機能を用いて、与えられたテキストの言語を自動判別して対応する言語のTTS Voiceで読み上げするAppleScriptです。Shane StanleyのAppleScript Libraryである「BridgePlus」(フリー)のインストールが必要です。

こういうのがやりたくて、地道に部品を揃えてきたわけで・・・やらないわけにはいきません。

ただし、思ったよりも泥沼に足を突っ込みかけました。食後のハイキングのはずが、雪山で遭難しかけたという印象です。

NSSpeechSynthesizerのavailableVoices()は「インストールされていないTTS Voice」も返してくるため、せっかくテキストの言語を特定して、TTS Voiceを取得しても・・・インストールされていないTTS Voiceが返ってくるとお手上げです(T_T)。

tts_voice_list.png

英語だとNSLinguisticTaggerによる判定で”en”が、フランス語だと”fr”が返ってきますが、”en”はあくまで英語を示すものであり、”en_GB”もあれば”en_US”もあれば、”en_IN”(インド)、”en-scotland”(スコットランド)、”en_ZA”(南アフリカ)もあるわけです(自分も物好きですが、南アフリカのTTS Voiceはインストールしていません)。

“en”をキーにして、全TTS Voiceから言語コードを取得し、最初にヒットした言語コードが”en_ZA”であれば南アフリカのTTS Voiceでsayコマンドの実行を行おうとしてしまうので、”en”を”en-US”に置き換えるような、つじつまあわせの処理が必要になってしまいました(もう少しうまいやり方もありそうですが、食後の散歩のレベルを超えてしまいますので)。

実際に実戦レベルのAppleScriptを書いてみるまで、見えてこない「落とし穴」もあるので、こうして細かいScriptを書いておくという作業はなかなかあなどれません、、、

AppleScript名:与えられたテキストの言語を自動判別して対応する言語のTTS Voiceで読み上げ
– Created 2015-09-11 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use BridgePlus : script “BridgePlus”

load framework

set aRes to getVoiceLanguageFromTTSVoices() –Language Code

–English, French, Japanese, Chinese
set cList to {“With the new MacBook, we set out to do the impossible.”, “Le nouveau MacBook est le résultat d’un défi presque impossible”, “新しいMacBookとともに、私たちは不可能だと思えることに挑みました。”, 于全新 MacBook,我们给自己定了一个几乎不可能实现的目}

–各言語テキストでループ
repeat with i in cList
  set j to contents of i
  
set aLang to specifyLanguageOfText(j) –テキストから言語コードを取得
  
  
–つじつまあわせ。ちょっとカッコ悪い
  
–(NSSpeechSynthesizerのavailableVoicesでインストールされていないVoiceまで返ってくることへの対策)
  
if aLang = “en” then
    set aLang to “en-US”
  else if aLang = “fr” then
    set aLang to “fr-FR”
  else if aLang = “ja” then
    set aLang to “ja-JP”
  end if
  
  
–全ボイス中から言語をサポートしているものを抽出
  
repeat with ii in aRes
    set jj to contents of ii
    
    
if (jj as text) is equal to (aLang as text) then
      
      
–最初にヒットした言語コードでPremium Voiceを検索
      
set v1fList to getPremiumVoiceNameWithFiltering(“VoiceGenderFemale”, jj)
      
set v1mList to getPremiumVoiceNameWithFiltering(“VoiceGenderMale”, jj)
      
set v1List to v1fList & v1mList
      
      
if v1List = {} then
        –Premium Voiceでヒットしなかった場合に、すべてのVoiceを検索
        
set v2fList to getAllVoiceNameWithFiltering(“VoiceGenderFemale”, jj)
        
set v2mList to getAllVoiceNameWithFiltering(“VoiceGenderMale”, jj)
        
set v2List to v2fList & v2mList
        
        
if v2List = {} then
          display dialog “この言語(” & jj & “)をサポートするTTS Voiceはインストールされていません。” –Error
          
exit repeat
        else
          copy v2List to v1List
        end if
        
      end if
      
      
repeat with iii in v1List
        set aVoice to contents of iii
        
try
          –総当たりでSayコマンド実行(インストールされていないTTS Voiceも取得できてしまうため)
          
tell current application
            say j using aVoice
          end tell
          
exit repeat
        end try
      end repeat
      
      
exit repeat
    end if
  end repeat
  
end repeat

–Premium Voices Only
on getPremiumVoiceNameWithFiltering(voiceGender, voiceLang)
  –Make Blank Array
  
set outArray to current application’s NSMutableArray’s arrayWithObject:{}
  
  
–Make Installed Voice List
  
set aList to current application’s NSSpeechSynthesizer’s availableVoices()
  
set bList to aList as list
  
  
repeat with i in bList
    set j to contents of i
    
set aDIc to (current application’s NSSpeechSynthesizer’s attributesForVoice:j)
    (
outArray’s addObject:aDIc)
  end repeat
  
  
–Filter Voice
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat_(“VoiceLanguage == %@ and VoiceGender == %@ and VoiceIdentifier ENDSWITH[c] %@”, voiceLang, voiceGender, “premium”)
  
set filteredArray to outArray’s filteredArrayUsingPredicate:aPredicate
  
set aReList to (filteredArray’s valueForKey:“VoiceName”) as list
  
  
return aReList
  
end getPremiumVoiceNameWithFiltering

–All Voices (VoiceLanguageで抽出)
on getAllVoiceNameWithFiltering(voiceGender, voiceLang)
  –Make Blank Array
  
set outArray to current application’s NSMutableArray’s arrayWithObject:{}
  
  
–Make Installed Voice List
  
set aList to current application’s NSSpeechSynthesizer’s availableVoices()
  
set bList to aList as list
  
  
repeat with i in bList
    set j to contents of i
    
set aDIc to (current application’s NSSpeechSynthesizer’s attributesForVoice:j)
    (
outArray’s addObject:aDIc)
  end repeat
  
  
–Filter Voice
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat_(“VoiceLanguage == %@ and VoiceGender == %@”, voiceLang, voiceGender)
  
  
set filteredArray to outArray’s filteredArrayUsingPredicate:aPredicate
  
set aReList to (filteredArray’s valueForKey:“VoiceName”) as list
  
  
return aReList
  
end getAllVoiceNameWithFiltering

on getLocaleIdentifierFromTTSVoices()
  –Make Blank Array
  
set outArray to current application’s NSMutableArray’s arrayWithObject:{}
  
  
–Make Installed Voice List
  
set aList to current application’s NSSpeechSynthesizer’s availableVoices()
  
set bList to aList as list
  
  
repeat with i in bList
    set j to contents of i
    
set aDIc to (current application’s NSSpeechSynthesizer’s attributesForVoice:j)
    (
outArray’s addObject:aDIc)
  end repeat
  
  
set aResArray to (outArray’s valueForKey:“VoiceLocaleIdentifier”)
  
  
set aSet to current application’s NSMutableSet’s setWithArray:aResArray
  
set aResList to aSet’s allObjects()
  
set bResList to BridgePlus’s listByDeletingBlanksIn:aResList –Remove Blank Items
  
  
return bResList
end getLocaleIdentifierFromTTSVoices

on getVoiceLanguageFromTTSVoices()
  –Make Blank Array
  
set outArray to current application’s NSMutableArray’s arrayWithObject:{}
  
  
–Make Installed Voice List
  
set aList to current application’s NSSpeechSynthesizer’s availableVoices()
  
set bList to aList as list
  
  
repeat with i in bList
    set j to contents of i
    
set aDIc to (current application’s NSSpeechSynthesizer’s attributesForVoice:j)
    (
outArray’s addObject:aDIc)
  end repeat
  
  
set aResArray to (outArray’s valueForKey:“VoiceLanguage”)
  
set aSet to current application’s NSMutableSet’s setWithArray:aResArray
  
set aResList to aSet’s allObjects()
  
set bResList to BridgePlus’s listByDeletingBlanksIn:aResList –Remove Blank Items
  
  
return bResList
end getVoiceLanguageFromTTSVoices

on specifyLanguageOfText(aStr)
  set aNSstring to current application’s NSString’s stringWithString:aStr
  
set tagSchemes to current application’s NSArray’s arrayWithObjects:(current application’s NSLinguisticTagSchemeLanguage)
  
set tagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:tagSchemes options:0
  
tagger’s setString:aNSstring
  
set aLanguage to tagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value)
  
return aLanguage as text
end specifyLanguageOfText

–1D Listをユニーク化してソート
on uniquifyAndSort1DList(theList as list, aBool as boolean)
  set aArray to current application’s NSArray’s arrayWithArray:theList
  
set bArray to aArray’s valueForKeyPath:“@distinctUnionOfObjects.self”
  
set aDdesc to current application’s NSSortDescriptor’s sortDescriptorWithKey:“self” ascending:aBool selector:“compare:”
  
set cArray to bArray’s sortedArrayUsingDescriptors:{aDdesc}
  
set bList to (ASify from cArray) as list
  
return bList
end uniquifyAndSort1DList

–文字置換
on repChar(aStr, targStr, repStr)
  set aString to current application’s NSString’s stringWithString:aStr
  
set bString to aString’s stringByReplacingOccurrencesOfString:targStr withString:repStr
  
set cString to (ASify from bString) as string
  
return cString
end repChar

★Click Here to Open This Script 

2015/09/10 テキストの言語を推測する

Cocoaの機能を用いて、与えられたテキストがどの言語のものかをNSLinguisticTaggerで求めるAppleScriptです。

資料がさほど多くないうえに、落とし穴(Blocks構文はAppleScriptにBridgeしてもらえないので、Blocks構文が必要なAPIは呼び出せない。なんとかしてほしいんですけど〜)を避けなければならないため、短い割には調査に苦労しました(プログラミングではなくて、調査なんですね、コレは)。

形態素解析ぐらいは、Blocksなしで呼び出してみたいもんです。

AppleScript名:テキストの言語を推測する
– Created 2015-09-10 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”

–English Text
set aStr to “With the new MacBook, we set out to do the impossible: engineer a full-size experience into the lightest and most compact Mac notebook ever. That meant reimagining every element to make it not only lighter and thinner but also better. The result is more than just a new notebook. It’s the future of the notebook.”
set aLang to specifyLanguageOfText(aStr)
–>  ”en”

–French Text
set aStr to “Le nouveau MacBook est le résultat d’un défi presque impossible : concevoir le Mac portable le plus léger et le plus compact jamais créé, sans dénaturer l’expérience Mac. Pour en arriver là, il nous a fallu repenser tous les éléments un à un, pour les rendre non seulement plus légers et plus fins, mais aussi plus perfectionnés. Le fruit de notre travail est bien plus qu’un nouvel ordinateur portable. C’est l’avenir de l’ordinateur portable.”
set aLang to specifyLanguageOfText(aStr)
–>  ”fr”

–Japanese Text
set aStr to “新しいMacBookとともに、私たちは不可能だと思えることに挑みました。これまでで最も軽く、最もコンパクトなMacのノートブックに、フルサイズの体験を与える、という目標です。それは、すべての要素をより軽く、より薄いものにするだけでなく、より優れたものにすることを意味しました。だから私たちは、すべての要素を一から考え直したのです。その結果、一台の新しいノートブック以上のものが生まれました。ノートブックの未来です。”
set aLang to specifyLanguageOfText(aStr)
–>  ”ja”

–Chinese Text
set aStr to 于全新 MacBook,我们给自己定了一个几乎不可能实现的目:在更为轻紧凑的 Mac 电脑之上,打造全尺寸的使用体就要求个元素都必重新想,不令其更为纤巧,要更加出色。最们带来的,不是一部全新的电脑,更是电脑的未来。”
set aLang to specifyLanguageOfText(aStr)
–>  ”zh-Hans”

on specifyLanguageOfText(aStr)
  set aNSstring to current application’s NSString’s stringWithString:aStr
  
set tagSchemes to current application’s NSArray’s arrayWithObjects:(current application’s NSLinguisticTagSchemeLanguage)
  
set tagger to current application’s NSLinguisticTagger’s alloc()’s initWithTagSchemes:tagSchemes options:0
  
tagger’s setString:aNSstring
  
set aLanguage to tagger’s tagAtIndex:0 |scheme|:(current application’s NSLinguisticTagSchemeLanguage) tokenRange:(missing value) sentenceRange:(missing value)
  
return aLanguage as text
end specifyLanguageOfText

★Click Here to Open This Script