はじめに
GitHub Copilotは、AIを活用したコード補助ツールで、様々なプログラミング言語やフレームワークに対応しています。
本記事では、同じ内容の指示を日本語・英語・中国語でCopilotに与えた場合、どのように出力が異なるかを検証します。
iOS開発者として、特にSwiftのコード生成を例に取りながら比較します。
テスト環境と方法
- 開発環境: VSCode + GitHub Copilotプラグイン(バージョン: 1.372.0)
- 利用モデル: GPT-4.1 Copilot(gpt-41-copilot)
- 言語: Swift(SwiftUI)
- テスト内容: 以下の条件を満たすSwiftUIの商品管理画面を作成する指示を、日本語・英語・中国語でそれぞれ入力
- 上部に商品名を入力するテキストフィールドと「商品追加」ボタンがある
- 商品名を入力してボタンを押すと商品がリストに追加される
- 空入力や重複入力の場合はエラー表示
- 商品リストは削除可能
- 各商品に「編集」ボタンがあり、商品名の変更が可能
- 最大5件まで商品追加可能
- 比較ポイント: コードの完成度、UIのエラー表示方法、コメントの有無、コードの読みやすさなど
生成コードの概要と違い
コード全文は長いため割愛し、各言語で特徴的な部分を抜粋し比較します。
日本語版
アラート表示部分

エラー時は以下のように呼び出す

- エラー表示は標準のモーダルアラートを使用
- 変数名・関数名も日本語に適した命名(例:showAlertMsg)
- コード本体がわかりやすい設計
英語版
アラート表示部分

エラー時は以下のように呼び出す

- 日本語版とほぼ同じエラー表示(モーダルアラート)
- 関数名・変数名も英語で自然に命名
- コードロジック・UI構造は非常に似ている
中国語版
エラーは画面内テキストで表示

エラー表示用関数

- モーダルアラートではなく、画面上に赤文字でエラーメッセージを表示するUI設計
- 変数名や関数名も「Error」を使うなどUIロジックに合わせた命名
- エラーメッセージの表示方法が一番異なるポイント
比較と考察
- 英語版は日本語版とほぼ差異がなく、Copilotが言語間で同様の出力を行っていることがわかる
- 中国語版はエラー表示UIの設計思想が異なり、モーダルを使わず画面内表示を選択。これがコード全体の雰囲気やユーザビリティに影響を与えている
- 中国語版はエラーの見せ方を簡潔にしており、結果として「コード本体に重きを置く」という印象を受けた可能性がある
- 変数名・関数名はそれぞれの言語の慣習に従い、自然な命名がされている
おわりに
今回の比較を通じて、多言語での指示がGitHub Copilotのアウトプットに細かな違いをもたらすことがわかりました。
特にエラー表示のUI設計や関数命名において、言語圏ごとの特徴が反映されていました。
iOS開発者としては、英語の活用をベースにしつつ、必要に応じて日本語や中国語の指示も試し、ツールの特性を活かすことが望ましいでしょう。
今後もAIツールをうまく活用し、開発効率をさらに高めていきたいと思います。
追加資料:コード全文
日本語の完全版コード
import SwiftUI
struct ProductManagerView: View {
@State private var products: [String] = []
@State private var inputText: String = ""
@State private var showAlert: Bool = false
@State private var alertMessage: String = ""
@State private var editingIndex: Int? = nil
@State private var editingText: String = ""
var body: some View {
VStack(alignment: .leading, spacing: 16) {
HStack {
TextField("商品名を入力", text: $inputText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(maxWidth: 200)
Button("商品追加") {
addProduct()
}
.disabled(products.count >= 5)
}
.padding(.top)
Text("商品リスト(\(products.count)/5):")
.font(.headline)
List {
ForEach(products.indices, id: \ .self) { idx in
HStack {
if editingIndex == idx {
TextField("商品名", text: $editingText)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button("保存") {
saveEdit(idx: idx)
}
Button("キャンセル") {
editingIndex = nil
editingText = ""
}
} else {
Text(products[idx])
Spacer()
Button("編集") {
editingIndex = idx
editingText = products[idx]
}
}
}
}
.onDelete(perform: deleteProduct)
}
.frame(maxHeight: 300)
}
.padding()
.alert(isPresented: $showAlert) {
Alert(title: Text("エラー"), message: Text(alertMessage), dismissButton: .default(Text("OK")))
}
}
private func addProduct() {
let trimmed = inputText.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else {
showAlertMsg("商品名を入力してください")
return
}
guard !products.contains(trimmed) else {
showAlertMsg("同じ商品名が既に存在します")
return
}
guard products.count < 5 else {
showAlertMsg("商品は最大5件までです")
return
}
products.append(trimmed)
inputText = ""
}
private func deleteProduct(at offsets: IndexSet) {
products.remove(atOffsets: offsets)
if let idx = editingIndex, offsets.contains(idx) {
editingIndex = nil
editingText = ""
}
}
private func saveEdit(idx: Int) {
let trimmed = editingText.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else {
showAlertMsg("商品名を入力してください")
return
}
if products.contains(trimmed) && products[idx] != trimmed {
showAlertMsg("同じ商品名が既に存在します")
return
}
products[idx] = trimmed
editingIndex = nil
editingText = ""
}
private func showAlertMsg(_ msg: String) {
alertMessage = msg
showAlert = true
}
}
struct ProductManagerView_Previews: PreviewProvider {
static var previews: some View {
ProductManagerView()
}
}英語版のコードは日本語版とほぼ同一のため、掲載を省略しています。
中国語の完全版コード
import SwiftUI
struct ProductManagerView: View {
@State private var products: [String] = []
@State private var inputText: String = ""
@State private var showError: Bool = false
@State private var errorMessage: String = ""
@State private var editingIndex: Int? = nil
@State private var editingText: String = ""
var body: some View {
VStack(alignment: .leading, spacing: 16) {
HStack {
TextField("请输入商品名", text: $inputText)
.textFieldStyle(RoundedBorderTextFieldStyle())
.frame(maxWidth: 200)
Button("添加商品") {
addProduct()
}
.disabled(products.count >= 5)
}
.padding(.top)
if showError {
Text(errorMessage)
.foregroundColor(.red)
}
Text("商品列表(\(products.count)/5):")
.font(.headline)
List {
ForEach(products.indices, id: \ .self) { idx in
HStack {
if editingIndex == idx {
TextField("商品名", text: $editingText)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button("保存") {
saveEdit(idx: idx)
}
Button("取消") {
editingIndex = nil
editingText = ""
}
} else {
Text(products[idx])
Spacer()
Button("编辑") {
editingIndex = idx
editingText = products[idx]
}
}
}
}
.onDelete(perform: deleteProduct)
}
.frame(maxHeight: 300)
}
.padding()
}
private func addProduct() {
let trimmed = inputText.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else {
showErrorMsg("商品名不能为空")
return
}
guard !products.contains(trimmed) else {
showErrorMsg("商品已存在")
return
}
guard products.count < 5 else {
showErrorMsg("最多只能添加5个商品")
return
}
products.append(trimmed)
inputText = ""
showError = false
}
private func deleteProduct(at offsets: IndexSet) {
products.remove(atOffsets: offsets)
if let idx = editingIndex, offsets.contains(idx) {
editingIndex = nil
editingText = ""
}
}
private func saveEdit(idx: Int) {
let trimmed = editingText.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else {
showErrorMsg("商品名不能为空")
return
}
if products.contains(trimmed) && products[idx] != trimmed {
showErrorMsg("商品已存在")
return
}
products[idx] = trimmed
editingIndex = nil
editingText = ""
showError = false
}
private func showErrorMsg(_ msg: String) {
errorMessage = msg
showError = true
}
}
struct ProductManagerView_Previews: PreviewProvider {
static var previews: some View {
ProductManagerView()
}
}







