unihan_lang 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/HOW_TO_UPDATE.md +13 -0
- data/README.ja.md +1 -0
- data/README.md +2 -1
- data/bump_new_version.sh +38 -0
- data/lib/unihan_lang/chinese_score_analyzer.rb +77 -0
- data/lib/unihan_lang/variant_mapping.rb +46 -0
- data/lib/unihan_lang/version.rb +1 -1
- data/lib/unihan_lang.rb +19 -10
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 838b5d8575bc79d05a24ed6555b9fe8d7856779b1f06e11ddbe3ae08e7030f11
|
|
4
|
+
data.tar.gz: b0e38c1bacc89a87f227ede35cef8b1985688b781bc9ebaf5a4f37ea29b378d7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '0482b7206764fc812703fefcb37badb8a59cdd2a88fb04741ae4e25c7380c83f08e293992a6ec3158ff8d296c2c790d111b16e16fa48bb825a1b4091e1da2c1f'
|
|
7
|
+
data.tar.gz: 7613e83a5579b1a45c9fdb4ef8d8df549f7f5dd95a5d7110dd5ca36c471cfcbcc410debfb9d15ca59927656699f756877051e9f49649ec5e01d98fcb5631f6b5
|
data/Gemfile.lock
CHANGED
data/HOW_TO_UPDATE.md
ADDED
data/README.ja.md
CHANGED
data/README.md
CHANGED
|
@@ -71,7 +71,7 @@ puts unihan.contains_zh_cn?("這個text不包含簡體字") # => false
|
|
|
71
71
|
|
|
72
72
|
## Features
|
|
73
73
|
|
|
74
|
-
- `determine_language(text)`: Determines the language of the text ("
|
|
74
|
+
- `determine_language(text)`: Determines the language of the text ("zh_TW", "zh_CN", "JA", "Unknown").
|
|
75
75
|
- `zh_tw?(text)`: Checks if the text is in Traditional Chinese.
|
|
76
76
|
- `zh_cn?(text)`: Checks if the text is in Simplified Chinese.
|
|
77
77
|
- `contains_chinese?(text)`: Checks if the text contains Chinese characters.
|
|
@@ -86,3 +86,4 @@ puts unihan.contains_zh_cn?("這個text不包含簡體字") # => false
|
|
|
86
86
|
This library does not guarantee 100% accuracy in language identification.
|
|
87
87
|
Particularly for short texts or texts containing multiple languages, determination may be challenging.
|
|
88
88
|
The distinction between Traditional and Simplified Chinese is based on the Unihan database.
|
|
89
|
+
Punctuation, digits, and whitespace are ignored when judging a sentence, and text containing Hiragana/Katakana is treated as Japanese rather than Chinese.
|
data/bump_new_version.sh
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
if [ -z "$1" ]; then
|
|
4
|
+
echo "Usage: $0 <version>"
|
|
5
|
+
exit 1
|
|
6
|
+
fi
|
|
7
|
+
|
|
8
|
+
# ~/.gem/credentials
|
|
9
|
+
if [ ! -f ~/.gem/credentials ]; then
|
|
10
|
+
echo "Error: ~/.gem/credentials not found. Please set up your RubyGems credentials."
|
|
11
|
+
exit 1
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
PROJECT_NAME="unihan_lang"
|
|
15
|
+
GITHUB_REPO="kyubey1228/unihan_lang"
|
|
16
|
+
VERSION=$1
|
|
17
|
+
echo "Start bumping version: $VERSION"
|
|
18
|
+
|
|
19
|
+
# Publish
|
|
20
|
+
# Add release branch
|
|
21
|
+
git checkout master
|
|
22
|
+
git checkout -b release/$VERSION
|
|
23
|
+
sed -i '' "s/VERSION = \".*\"/VERSION = \"$VERSION\"/" lib/$PROJECT_NAME/version.rb
|
|
24
|
+
git commit -am "Bump version $VERSION"
|
|
25
|
+
|
|
26
|
+
# Publish to rubygems
|
|
27
|
+
gem build $PROJECT_NAME.gemspec
|
|
28
|
+
bundle install
|
|
29
|
+
gem push $PROJECT_NAME-$VERSION.gem
|
|
30
|
+
|
|
31
|
+
# GitHub release
|
|
32
|
+
git tag $VERSION
|
|
33
|
+
git push --tags
|
|
34
|
+
open https://github.com/$GITHUB_REPO/releases/new
|
|
35
|
+
|
|
36
|
+
# merge to master
|
|
37
|
+
git checkout master
|
|
38
|
+
git merge release/$VERSION
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module UnihanLang
|
|
4
|
+
class ChineseScoreAnalyzer
|
|
5
|
+
attr_reader :traditional_score, :simplified_score, :total_chinese
|
|
6
|
+
|
|
7
|
+
def initialize(text, chinese_processor, variant_mapping)
|
|
8
|
+
@text = text
|
|
9
|
+
@chinese_processor = chinese_processor
|
|
10
|
+
@variant_mapping = variant_mapping
|
|
11
|
+
@traditional_score = 0
|
|
12
|
+
@simplified_score = 0
|
|
13
|
+
@contains_kana = false
|
|
14
|
+
analyze
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def dominant_language
|
|
18
|
+
return "Unknown" if contains_kana?
|
|
19
|
+
return "Unknown" if total_chinese.zero?
|
|
20
|
+
return "ZH_TW" if traditional_score > simplified_score
|
|
21
|
+
return "ZH_CN" if simplified_score > traditional_score
|
|
22
|
+
|
|
23
|
+
"Unknown"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def language_ratio
|
|
27
|
+
return :unknown if contains_kana?
|
|
28
|
+
return :unknown if total_chinese.zero? || total_chinese != meaningful_length
|
|
29
|
+
return :tw if traditional_score > simplified_score
|
|
30
|
+
return :cn if simplified_score > traditional_score
|
|
31
|
+
|
|
32
|
+
:unknown
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def contains_kana?
|
|
38
|
+
@contains_kana
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def kana_char?(char)
|
|
42
|
+
ord = char.ord
|
|
43
|
+
# 0x3040-0x309F: ひらがな, 0x30A0-0x30FF: カタカナ, 0x31F0-0x31FF: カタカナ拡張
|
|
44
|
+
(ord >= 0x3040 && ord <= 0x309F) || (ord >= 0x30A0 && ord <= 0x30FF) || (ord >= 0x31F0 && ord <= 0x31FF)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Punctuation, digits, and whitespace are ignored so they don't
|
|
48
|
+
# invalidate an otherwise all-Chinese sentence (e.g. "這是中文。").
|
|
49
|
+
def meaningful_length
|
|
50
|
+
@text.chars.count { |char| char.match?(/\p{L}/) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def analyze
|
|
54
|
+
@total_chinese = 0
|
|
55
|
+
@text.chars.each do |char|
|
|
56
|
+
@contains_kana ||= kana_char?(char)
|
|
57
|
+
|
|
58
|
+
next unless @chinese_processor.chinese_character?(char)
|
|
59
|
+
|
|
60
|
+
@total_chinese += 1
|
|
61
|
+
|
|
62
|
+
calculate_character_scores(char)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def calculate_character_scores(char)
|
|
67
|
+
if @chinese_processor.only_zh_tw?(char)
|
|
68
|
+
@traditional_score += 2
|
|
69
|
+
elsif @chinese_processor.only_zh_cn?(char)
|
|
70
|
+
@simplified_score += 2
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
@traditional_score += 0.5 if @variant_mapping.traditional_variants(char).any?
|
|
74
|
+
@simplified_score += 0.5 if @variant_mapping.simplified_variants(char).any?
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module UnihanLang
|
|
4
|
+
class VariantMapping
|
|
5
|
+
def initialize
|
|
6
|
+
@traditional_to_simplified = load_variant_mappings
|
|
7
|
+
@simplified_to_traditional = {}
|
|
8
|
+
# 簡体字から繁体字へのマッピングを構築
|
|
9
|
+
@traditional_to_simplified.each do |trad, simps|
|
|
10
|
+
simps.each do |simp|
|
|
11
|
+
@simplified_to_traditional[simp] ||= Set.new
|
|
12
|
+
@simplified_to_traditional[simp] << trad
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def traditional_variants(char)
|
|
18
|
+
@simplified_to_traditional[char] || Set.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def simplified_variants(char)
|
|
22
|
+
@traditional_to_simplified[char] || Set.new
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def load_variant_mappings
|
|
28
|
+
traditional_to_simplified = {}
|
|
29
|
+
file_path = File.join(File.dirname(__FILE__), "..", "..", "data", "Unihan_Variants.txt")
|
|
30
|
+
|
|
31
|
+
File.foreach(file_path, encoding: "UTF-8") do |line|
|
|
32
|
+
next if line.start_with?("#") || line.strip.empty?
|
|
33
|
+
|
|
34
|
+
fields = line.strip.split("\t")
|
|
35
|
+
# kTraditionalVariant フィールドの場合のみ処理
|
|
36
|
+
if fields.size >= 3 && fields[1] == ("kTraditionalVariant")
|
|
37
|
+
simp = [fields[0].gsub(/^U\+/, "").hex].pack("U")
|
|
38
|
+
trad = [fields[2].gsub(/^U\+/, "").hex].pack("U")
|
|
39
|
+
traditional_to_simplified[trad] ||= Set.new
|
|
40
|
+
traditional_to_simplified[trad] << simp
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
traditional_to_simplified
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
data/lib/unihan_lang/version.rb
CHANGED
data/lib/unihan_lang.rb
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "unihan_lang/version"
|
|
4
4
|
require_relative "unihan_lang/chinese_processor"
|
|
5
|
+
require_relative "unihan_lang/variant_mapping"
|
|
6
|
+
require_relative "unihan_lang/chinese_score_analyzer"
|
|
5
7
|
|
|
6
8
|
module UnihanLang
|
|
7
9
|
class Unihan
|
|
8
10
|
def initialize
|
|
9
11
|
@chinese_processor = ChineseProcessor.new
|
|
12
|
+
@variant_mapping = VariantMapping.new
|
|
10
13
|
end
|
|
11
14
|
|
|
12
15
|
def zh_tw?(text)
|
|
@@ -49,19 +52,25 @@ module UnihanLang
|
|
|
49
52
|
end
|
|
50
53
|
end
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
def analyze_with_variants(text)
|
|
56
|
+
analyzer = ChineseScoreAnalyzer.new(text, @chinese_processor, @variant_mapping)
|
|
57
|
+
{
|
|
58
|
+
traditional_score: analyzer.traditional_score,
|
|
59
|
+
simplified_score: analyzer.simplified_score,
|
|
60
|
+
total_chinese: analyzer.total_chinese,
|
|
61
|
+
}
|
|
62
|
+
end
|
|
53
63
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
chinese_chars = text.chars.count { |char| @chinese_processor.chinese?(char) }
|
|
64
|
+
def determine_language_with_variants(text)
|
|
65
|
+
analyzer = ChineseScoreAnalyzer.new(text, @chinese_processor, @variant_mapping)
|
|
66
|
+
analyzer.dominant_language
|
|
67
|
+
end
|
|
59
68
|
|
|
60
|
-
|
|
61
|
-
return :tw if only_tw_chars > only_cn_chars
|
|
62
|
-
return :cn if only_cn_chars >= only_tw_chars
|
|
69
|
+
private
|
|
63
70
|
|
|
64
|
-
|
|
71
|
+
def language_ratio(text)
|
|
72
|
+
analyzer = ChineseScoreAnalyzer.new(text, @chinese_processor, @variant_mapping)
|
|
73
|
+
analyzer.language_ratio
|
|
65
74
|
end
|
|
66
75
|
end
|
|
67
76
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: unihan_lang
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- kyubey1228
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2026-08-17 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: bundler
|
|
@@ -66,20 +65,23 @@ files:
|
|
|
66
65
|
- ".rubocop.yml"
|
|
67
66
|
- Gemfile
|
|
68
67
|
- Gemfile.lock
|
|
68
|
+
- HOW_TO_UPDATE.md
|
|
69
69
|
- LICENSE.md
|
|
70
70
|
- README.ja.md
|
|
71
71
|
- README.md
|
|
72
72
|
- Rakefile
|
|
73
|
+
- bump_new_version.sh
|
|
73
74
|
- data/Unihan_Variants.txt
|
|
74
75
|
- lib/unihan_lang.rb
|
|
75
76
|
- lib/unihan_lang/chinese_processor.rb
|
|
77
|
+
- lib/unihan_lang/chinese_score_analyzer.rb
|
|
78
|
+
- lib/unihan_lang/variant_mapping.rb
|
|
76
79
|
- lib/unihan_lang/version.rb
|
|
77
80
|
- unihan_lang.gemspec
|
|
78
81
|
homepage: https://github.com/kyubey1228/unihan_lang
|
|
79
82
|
licenses:
|
|
80
83
|
- MIT
|
|
81
84
|
metadata: {}
|
|
82
|
-
post_install_message:
|
|
83
85
|
rdoc_options: []
|
|
84
86
|
require_paths:
|
|
85
87
|
- lib
|
|
@@ -94,8 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
94
96
|
- !ruby/object:Gem::Version
|
|
95
97
|
version: '0'
|
|
96
98
|
requirements: []
|
|
97
|
-
rubygems_version: 3.
|
|
98
|
-
signing_key:
|
|
99
|
+
rubygems_version: 3.6.2
|
|
99
100
|
specification_version: 4
|
|
100
101
|
summary: Language detection for Chinese characters
|
|
101
102
|
test_files: []
|