読者です 読者をやめる 読者になる 読者になる

しばやん雑記

ASP.NET とメイドさんが大好きなフリーランスのプログラマーのブログ

ResXManager を使って UWP アプリケーションの多言語対応を簡単に行う

Visual Studio UWP

UWP アプリケーションを作った場合には、日本語だけの対応だとダウンロード数が伸びにくいので、出来れば多言語に対応しておいた方が良さそうです。

これまで手動で頑張って ResX を追加するという、非常に生産的ではないことを行なっていましたが、Visual Studio に神拡張機能があることを知ったので試しました。

ResXManager - Visual Studio Marketplace

ResX をキー名ベースで編集できるだけでも便利なのですが、Microsoft Translator や Bing Translator を使って、自動的に機械翻訳された ResX を作ってくれます。

今回は手軽な Cognitive Services の Translator Text API を使ってみました。Azure Portal で Cognitive Services のアカウントを新しく作ります。API Type を Translator Text API にするのを忘れないように。

f:id:shiba-yan:20170220130609p:plain

作成が終わったらアクセスキーをコピーしておきます。これを ResXManager に設定する必要があります。

f:id:shiba-yan:20170220135531p:plain

翻訳の準備が出来たので、新しく UWP アプリケーションを作成して、最初に元になる言語リソースを追加しておきます。今回は日本語をベースに各言語に翻訳するので、ja-JP でリソースを作成しておきました。

予めキーとテキストを入力しておきます。最初の 1 つ目はファイルを作成しておかないといけないようです。

f:id:shiba-yan:20170220140740p:plain

Visual Studio から ResXManager を開いて、新しく言語を追加します。まずはわかりやすいように en-US を追加しました。ダイアログでは入力補完が効くので簡単です。

f:id:shiba-yan:20170220135828p:plain

英語だけではつまらないと思ったので、ついでにドイツ語も追加してみました。この時点で ResXManager の表示は以下のようになっているはずです。

f:id:shiba-yan:20170220140412p:plain

言語を追加しただけではリソースファイル自体は生成されないのですが、赤くなっている部分のセルをダブルクリックするとファイル作成ダイアログが表示されるので、ここから作ることが出来ます。

これで機械翻訳 API の準備が出来たので、画面下にあるタブから Translate を選びます。上に機械翻訳サービスのタブがあるので、Azure を選んでコピーしておいたアクセスキーを張り付けておきます。

f:id:shiba-yan:20170220143248p:plain

Source と Target を選択しないといけないので、Source には日本語を Target には英語とドイツ語を選んでおきます。これで準備は完了です。

画面下にある Restart ボタンをクリックすると、翻訳が実際に行われます。

f:id:shiba-yan:20170220140509p:plain

翻訳結果はドロップダウンメニューにもなっているので、選択すると別の翻訳結果を見ることも出来ます。

今は Azure しか設定していないですが、他の API の設定を行うと、それぞれから最良の結果を選べるようになっているみたいですね。

f:id:shiba-yan:20170220143604p:plain

最後に Apply All か Apply Selected をクリックすると、実際にリソースファイルに反映されます。

f:id:shiba-yan:20170220140545p:plain

予め 1 つはリソースを作っておく必要はありますが、後は完全に自動で行えるのはかなり便利でした。

機械翻訳も最近はニューラルネットワークを使うことで質が上がっているので、かなり良い選択になった気がします。今回は UWP に対して使いましたが、当然ながら ASP.NET など ResX を使うアプリケーション全てに対応しています。

Azure Functions の Precompiled Functions が改善されたので GitHub 連携でデプロイを行ってみる

Azure Functions

以前にぶちぞう RD が試した時にはまだまだ初期実装で、一度アセンブリを読み込むとロックされて更新できなくなってましたが、今朝 Azure Functions のランタイムがアップデートされて解消したみたいです。

App Service を確認すると、既に最新のバージョンがインストールされていました。すぐに試せます。

ブラウザだけで開発できる手軽さは素敵ですが、やはり俺達には Visual Studio のエディターが必要でした。csx はまだまだ発展途上で、ツールの対応が追い付いていない感じです。

とまあ、個人的にはコンパイルして動かしたい派だったので、早速試すことにします。GitHub 上のリリースノートにある Shadow copy assemblies と Automatic runtime restart というのが重要です。

  • Shadow copy assemblies (#1169)
    • addresses file locking deployment issues for .NET languages
  • Automatic runtime restart on managed dependency updates
    • addresses issues where a manual restart was required to reflect assembly updates (#1023)
Release Functions 1.0.10756 · Azure/azure-webjobs-sdk-script · GitHub

Shadow copy assembiles の Pull Request は同じようにアセンブリを実行時に読み込んで、いろいろしたい人には参考になるコードという感じでした。

実行時のアップデートを確認

とりあえず、まずは手動で Function のコンパイルを行って、実行時のアップデートが行えるか確認します。利用したコードは Wiki に書いてあるものをそのまま使いました。

Precompiled functions · Azure/azure-webjobs-sdk-script Wiki · GitHub

Visual Studio でビルドして、Kudu を使って Function をデプロイします。

f:id:shiba-yan:20170216215210p:plain

Azure Portal での Precompiled Functions の表示も改善されていました。

使っているのが Preview Portal だからかも知れませんが、前までは dll を読み込んで無理やり表示していましたが、今は function.json が表示されます。

f:id:shiba-yan:20170216215121p:plain

サクッと動作を確認します。まずはアセンブリを読み込ませるために、適当にクエリパラメータを指定してテスト実行します。

f:id:shiba-yan:20170216215553p:plain

問題なく dll が読み込まれて実行されているようです。

次に Function を修正し、ビルドを行ったものを Kudu から直接上書きしてアップデートしてみます。実際に実行されているアセンブリは別の場所にあるので、問題なく上書きできます。そして同じく実行してみます。

f:id:shiba-yan:20170216215816p:plain

Azure Functions のランタイムが変更を検知して、自動的に新しいアセンブリを読み込んで実行してくれました。これで GitHub などからデプロイを行う準備が出来ました。

GitHub 連携でデプロイを行う

サンプルとして Azure Functions 向けのデプロイスクリプトを作成したリポジトリを公開しておきました。今のところ Function を追加する度に追記する必要がありますが、工夫次第で何とでもなる気がします。

将来的には KuduScript が Functions のデプロイスクリプトに対応する気がします。

ソリューションの構成は以下のようにしました。csx の時はディレクトリで分離されていましたが、1 プロジェクトが 1 つの Function に相当するように作ります。

f:id:shiba-yan:20170216222825p:plain

デプロイスクリプトを抜粋すると、プロジェクトをビルドして特定のディレクトリに出力しているだけです。

:: 2. Build to the temporary path
call :ExecuteCmd "%MSBUILD_PATH%" "%DEPLOYMENT_SOURCE%\HelloWorld\HelloWorld.csproj" /nologo /verbosity:m /t:Build /p:Configuration=Release;OutputPath="%DEPLOYMENT_TEMP%\HelloWorld";UseSharedCompilation=false %SCM_BUILD_ARGS%
IF !ERRORLEVEL! NEQ 0 goto error

元々は WebJob 用スクリプトを修正したものです。もうちょっと上手い方法がある気がします。

GitHub に push すると App Service がプロジェクトをビルドしてくれます。

f:id:shiba-yan:20170216223735p:plain

ちゃんと Kudu 上で確認しても、Functions の仕様通りにディレクトリが作られてることが分かります。基本的にディレクトリの規約ベースなので自動でのデプロイがしやすいです。

f:id:shiba-yan:20170216222938p:plain

Azure Portal でも作成した Function が認識されています。動作結果は同じなので省略しますが、当然ながら問題なく動作しました。CI 連携済みなので Read only になっています。

f:id:shiba-yan:20170216223958p:plain

もちろん GitHub のリポジトリを修正すると、ビルドされてアップデートが行われます。

これで Visual Studio を使って快適な開発を行いつつ、デプロイまで完全に自動で行えるようになりました。これまでに csx で書いた Functions を移行していこうかと思います。

HoloLens を使ってゲームが出来るのか試してみた

Windows

2017 年だし、ホログラフィック(自称)と名乗ってるし、このゲームは遊んでおかないといけないと思ったので、蛎殻町に放置されていた HoloLens を整備して試しました。

UWP 版の Remote Desktop アプリケーションを使って、ゲームをインストール済みのマシンに接続しました。Clicker が見つからなかったので、全ての操作をエアタップで行ったので腕がつりそうでした。

画面サイズはドラッグで自由に大きく出来るので、下の画像は 100 インチは超えてる気がします。

ちゃんと Remote Desktop でも音が出ます。少し帯域が足りない感じがしますが、Device Portal から Live Preview などを使わなければ割と頑張れました。

右クリックはゲームによっては出来ない場合がありそうなので、少し不便です。

App-V とかでアプリの画面だけを表示できれば、結構いい感じに遊べると思いました。キャラクターの声が耳元から聞こえてくるのは、やばさがあったと思います。HoloLens ネイティブのゲームを体験したい。

蛎殻町の若者やぶちぞう RD から Xbox One のゲームストリーミングが使えるのでは、と指摘を受けたので HoloLens を借りて自宅の Xbox One に接続してみました。

f:id:shiba-yan:20170215215832j:plain

スペック不足とか言われるのかと思いましたが、すんなりと本体が見つかってストリーミング接続できました。折角なので Forza Horizon 3 をプレイしてみました。

自宅の Wi-Fi は 11ac に対応しているので、思ったより遅延なくプレイできました。

アプリケーションは UWP にしか対応していないのが、正直もったいなく感じます。Unity は使える気がしないですが、UWP を使って HoloLens 向けのアプリケーションを作ってみたい気持ちになりました。

あと、やっぱり視野角が狭すぎると思うので、次のバージョンではもっと広くなって欲しいです。