0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

小道具:macOS用ファインダー向けディレクトリ国際化

Last updated at Posted at 2025-02-25

たとえば日本語ディレクトリ

% ls -1F
サンプル/

をファインダーでは見かけ上変化しないディレクトリ構造

sample.localized
   + .localized
      + ja.strings
          内容: "sample" = "サンプル";

に変更したいとき、コマンドラインで

% python3 ja2loca.py サンプル sample

として簡単に済ませるためスクリプトです。

処理内容

  1. 元ディレクトリに ".localized" ディレクトリを追加
  2. ".localized/ja.strings" ファイルを作成
  3. ディレクトリ名を変更

動作確認は macOS 15.3 で行っています。

エラー発生時の回復処理は行いません。ゴミが残ったり壊れた状態になることが予想されます。

ja2loca.py
#!/usr/bin/env python3

import argparse
import os
import sys
from os.path import stat


def noop(*_args, **_kwargs):
    pass


message = noop
verbose = noop


def xstat(path):
    try:
        return os.stat(path)
    except OSError:
        return None


class Failed(Exception):
    pass


def main():
    parser = argparse.ArgumentParser(description='macOS用ファインダー向けディレクトリ国際化')
    parser.add_argument('-q', '--quiet', action='store_true')
    parser.add_argument('-v', '--verbose', action='store_true')
    parser.add_argument('SRC', help='表示(旧ディレクトリ)名')
    parser.add_argument('NEW', help='ASCII名(.localized が追加される)')

    args = parser.parse_args()
    flag_quiet = args.quiet
    flag_verbose = args.verbose

    message = noop if flag_quiet else print
    verbose = message if flag_verbose else noop

    def warning(msg):
        message(f'warning: {msg}')

    def write_text(path, text):
        verbose(f'write: "{path}"')
        with open(path, 'w') as fp:
            fp.write(text)

    dot_loca = '.localized'

    def islocalized(path):
        return path[-len(dot_loca):] == dot_loca

    src_path = args.SRC.rstrip('/')
    src_stat = xstat(src_path)
    if not src_stat:
        raise Failed(f'"{src_path}" は存在しません')
    if not stat.S_ISDIR(src_stat.st_mode):
        raise Failed(f'"{src_path}" はディレクトリではありません')
    if islocalized(src_path):
        raise Failed(f'"{src_path}" の後置名が "{dot_loca}" です')
    ja_name = os.path.basename(src_path)

    new_path = args.NEW.rstrip('/')
    if islocalized(new_path):
        cut_path = new_path[:-len(dot_loca)]
        warning(f'"{new_path}" から "{dot_loca}" を削除した "{cut_path}" を使用します')
        new_path = cut_path
    new_stat = xstat(new_path)
    if new_stat:
        warning(f'"{new_path}" が存在します')
    en_name = os.path.basename(new_path)

    if en_name == ja_name:
        raise Failed(f'元と先が同じ名前 "{ja_name}" です')

    loc_path = f'{new_path}{dot_loca}'
    loc_stat = xstat(loc_path)
    if loc_stat:
        raise Failed(f'"{loc_path}" が存在します')

    str_path = f'{src_path}/{dot_loca}'
    str_stat = xstat(str_path)
    if not str_stat:
        verbose(f'mkdir: "{str_path}"')
        os.mkdir(str_path)
        str_stat = os.stat(str_path)
    if not stat.S_ISDIR(str_stat.st_mode):
        raise Failed(f'"{str_path}" はディレクトリではありません')

    write_text(f'{str_path}/ja.strings', f'"{en_name}" = "{ja_name}";\n')

    verbose(f'rename: "{src_path}""{loc_path}"')
    os.rename(src_path, loc_path)
    return 0


try:
    sys.exit(main())
except Failed as e:
    print(f'error: {e}')
    sys.exit(2)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?