Releases: Halvanhelv/translation_diff
Release list
v2.2.0
Message-only release. No code changes.
deepl_diff is being replaced by translation_diff, which supports translation providers other than DeepL. Installing this version now prints a pointer to it.
Anyone pinned to this version keeps working, and this gem will not change again — 2.2.0 is the last release under the name deepl_diff.
Why the rename
The gem contains no reference to DeepL beyond its own name. Since 2.0.0 the API object has been supplied by the application and duck typed on a single method, so the gem was already provider agnostic in everything but the name and the DeepL request limits hard-coded into the chunker. translation_diff states the adapter contract, moves those limits into the adapter, and keys the cache by provider.
Changes
deepl_diff.gemspec— adds a post-install messagelib/deepl_diff/version.rb— 2.1.0 → 2.2.0
Full changelog: v2.1.0...v2.2.0
v2.1.0
Six bugs found while auditing the library. Each was reproduced against the real library before being fixed, and each has a regression test.
All six are fixes, but DeepLDiff::Request::Error is a new public constant, hence the minor bump.
Fixed
The options hash was consumed, not read. #from and #to called Hash#delete on the caller's hash, so a second call with the same hash lost :from and :to and fell through to language detection. A frozen hash — which is what a hash of settings kept in a constant is — raised FrozenError on the very first call. The request copies the hash now.
The chunker measured three different things against one limit. #next_chunk? added the escaped size of the incoming value to a running total of raw String#size, #update_chunk accumulated the raw size, and #validate_value_size compared the raw size. Since CGI.escape inflates Cyrillic sixfold, a chunk of Russian text ran several times over the limit, and a single value whose request size was five times the limit passed validation. Chunking is the only guard against DeepL's request-size limit, and it did not work for any non-Latin text. Everything is measured escaped now — that is what goes over the wire.
A detected source language never matched the target. #detect_language returns a String while :to is usually a Symbol, so from == to could not fire and the text was paid for and translated into its own language. The two are compared case-insensitively as strings now. The cache key is deliberately left alone so existing cached entries stay valid.
A short API response surfaced two layers away. Missing translations shifted nil into the results, which showed up as NoMethodError: undefined method 'strip' for nil inside Spacing. DeepLDiff::Request::Error is raised at the call site now, before a nil can reach the cache.
Non-string scalars crashed. nil and Integer raised NoMethodError on #empty?, Symbol raised TypeError inside Ox. Such values pass through untouched now. nil keeps collapsing to "" inside a structure, exactly as before.
The count limit was off by one. The check ran after the value was added, so a chunk held count_limit + 1 texts.
Upgrade note
The chunker fix changes how non-Latin text is split: chunks are smaller, so there are more requests for the same number of characters billed. This is the correct behaviour, but if your MAX_CHUNK_SIZE was tuned empirically against Cyrillic, the default of 1700 now means a very different payload than it did.
Full changelog: v2.0.0...v2.1.0
v2.0.0
Major release. The gem now loads two runtime dependencies instead of eight.
Breaking changes
- Six runtime dependencies were removed. Applications relying on this gem to install the DeepL client,
redis,redis-namespace,connection_poolorratelimitmust now depend on them directly. The README example requires them explicitly. RedisRateLimitertakesthresholdandintervalas keywords. Callers passing them positionally must switch.
What was actually used
| gem | where its constant appears in lib/ |
verdict |
|---|---|---|
ox |
Ox::Sax, Ox.sax_parse in the tokenizer |
kept |
punkt-segmenter |
Punkt::SentenceTokenizer in the tokenizer |
kept |
dry-initializer |
five extend lines |
dropped |
connection_pool |
nowhere — the pool is duck typed on #with |
dropped |
redis |
nowhere — bare Redis is never named |
dropped |
deepl-rb |
nowhere — required at load, constant unused | dropped |
redis-namespace |
inside one method body of RedisCacheStore |
dropped |
ratelimit |
inside one method body of RedisRateLimiter |
dropped |
redis-namespace and ratelimit already resolved lazily — the gem loaded fine without them and only broke if you used those classes. Declaring them as hard dependencies forced them on everyone who ran their own cache store.
This is what the README always promised: "This dependencies are not included, as you might need to roll your own cache based on different store." The gemspec just never agreed with it.
Fixed
RedisRateLimiter declared threshold and interval as positional params, so the keyword call the README documents silently discarded them and fell back to 8000 and 60. They are keywords now, with a regression test.
Internal
dry-initializerwas replaced by plain initializers. Its generated readers were private, so the privateattr_readers that replace them leave the public API unchanged.- Both Redis wrappers had no tests at all; they have six now. Coverage went from 94.68% to 97.57%.
Full changelog: v1.1.1...v2.0.0
v1.1.1
Patch release. lib/ is unchanged since 1.1.0.
Changed
- The test suite moved from RSpec to Minitest (#3). This swaps the
rspecdevelopment dependency forminitest ~> 6.0and rewrites theRakefilearoundRake::TestTask— both ship inside the gem, hence the version bump. - The gem is now published from CI through RubyGems trusted publishing (#2), so releases no longer depend on a personal API key.
Full changelog: v1.1.0...v1.1.1
v1.1.0
Dependency and Ruby modernization. Every runtime dependency was unversioned and the development dependencies were pinned to Ruby 2.3-era releases; everything is now current with explicit constraints, and the gem requires Ruby >= 3.2.
Dependencies
| gem | before | after |
|---|---|---|
| connection_pool | unversioned | >= 2.4, < 4.0 |
| deepl-rb | unversioned | ~> 3.9 |
| dry-initializer | unversioned | ~> 3.2 |
| ox | unversioned | ~> 2.14 |
| punkt-segmenter | unversioned | ~> 0.9 |
| ratelimit | unversioned | ~> 1.1 |
| redis | unversioned | >= 5.0, < 7.0 |
| redis-namespace | unversioned | ~> 1.11 |
| rake | ~> 10.0 |
~> 13.0 |
| rspec | ~> 3.0 |
~> 3.13 |
| rubocop | unversioned | ~> 1.90 |
| simplecov | unversioned | ~> 1.2 |
| bundler | ~> 1.14 |
removed |
| codeclimate-test-reporter | ~> 1.0.0 |
removed (unmaintained) |
Compatibility fixes
- Require
cgi/escape,digest/md5,forwardableandstringioexplicitly. They used to be pulled in transitively, which no longer holds. - Pass the DeepL options as a positional hash.
deepl-rbdeclarestranslate(text, source_lang, target_lang, options = {}), so the**optionssplat passed nothing when the hash was empty. - Replace
OpenStructin the request spec with aStruct;OpenStructis no longer available without an explicit require. - Rename
Chunker::Chunkmembersvalues/sizetotexts/bytesizeso they stop shadowingStruct#valuesandStruct#size. - Move the
Tokenizerconstants above theprivatesection, where they are actually reachable.
CI and lint
- Replace Travis with GitHub Actions: the suite runs against Ruby 3.2, 3.3, 3.4 and 4.0, plus a RuboCop job.
- Update
.rubocop.ymlfor RuboCop 1.90 —TargetRubyVersion,NewCops: enable, andMetrics/LineLengthrenamed toLayout/LineLength.
Full changelog: v1.0.1...v1.1.0