Class: Multilocale::Phrases

Inherits:
Object
  • Object
show all
Defined in:
lib/multilocale/phrases.rb

Overview

/api/phrases. Reads need the phrases:read scope, writes phrases:write.

Constant Summary collapse

MAX_LIMIT =

Server-side caps, mirrored here so a bad page size fails locally with a useful message instead of being silently clamped.

2001
MAX_SKIP =
10_000
SORT_FIELDS =
%w[_id key language].freeze
DEFAULT_BATCH_SIZE =

POST accepts an array, but a few thousand rows in one body is how you meet a timeout. 200 is comfortably under it.

200

Instance Method Summary collapse

Constructor Details

#initialize(client) ⇒ Phrases

Returns a new instance of Phrases.



16
17
18
# File 'lib/multilocale/phrases.rb', line 16

def initialize(client)
  @client = client
end

Instance Method Details

#delete(key:, project:) ⇒ Object

Deletes EVERY language of key in project — a 30-locale key is 30 rows gone in one call. Rows shared with other projects are deleted too, not detached from this one. Returns the deleted rows.

Raises:

  • (ArgumentError)


88
89
90
91
92
93
94
# File 'lib/multilocale/phrases.rb', line 88

def delete(key:, project:)
  raise ArgumentError, "key is required" if key.nil? || key.to_s.empty?
  raise ArgumentError, "project is required" if project.nil? || project.to_s.empty?

  result = @client.delete("phrases", params: { "key" => Encoding.phrase_key(key), "project" => project })
  Array(result).map { |attributes| Phrase.new(attributes) }
end

#find_by_key(key, project: nil) ⇒ Object

Every row of one key, one per language.



52
53
54
# File 'lib/multilocale/phrases.rb', line 52

def find_by_key(key, project: nil)
  list(key: key, project: project)
end

#list(project: nil, language: nil, key: nil, fields: nil, limit: nil, skip: nil, sort_field: nil, sort_direction: nil) ⇒ Object

Omitting limit returns every matching row — the server treats a missing limit as unbounded, which is what a full dictionary download wants. Pass limit/skip only when you actually want a page.



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/multilocale/phrases.rb', line 23

def list(project: nil, language: nil, key: nil, fields: nil, limit: nil, skip: nil, sort_field: nil,
         sort_direction: nil)
  if limit && (limit.to_i < 1 || limit.to_i > MAX_LIMIT)
    raise ArgumentError, "limit must be between 1 and #{MAX_LIMIT} (got #{limit})"
  end

  if skip && (skip.to_i.negative? || skip.to_i > MAX_SKIP)
    raise ArgumentError, "skip must be between 0 and #{MAX_SKIP} (got #{skip})"
  end

  if sort_field && !SORT_FIELDS.include?(sort_field.to_s)
    raise ArgumentError, "sort_field must be one of #{SORT_FIELDS.join(', ')} (got #{sort_field})"
  end

  parameters = {
    "project" => project,
    "language" => language,
    "key" => (key && Encoding.phrase_key(key)),
    "fields" => (fields && Array(fields).join(",")),
    "limit" => limit,
    "skip" => skip,
    "sortField" => sort_field,
    "sortDirection" => sort_direction
  }

  Array(@client.get("phrases", params: parameters)).map { |attributes| Phrase.new(attributes) }
end

#update(id, attributes) ⇒ Object



81
82
83
# File 'lib/multilocale/phrases.rb', line 81

def update(id, attributes)
  Phrase.new(@client.put("phrases/#{Encoding.percent_encode(id)}", body: Phrase.to_api(attributes)))
end

#upsert(phrases = nil, batch_size: DEFAULT_BATCH_SIZE, **attributes) ⇒ Object

Creates or overwrites rows. A row with an _id that already exists is replaced wholesale (it is an upsert, not a patch): send the whole row.

phrases.upsert(key: "cart.title", value: "Cart", language: "en", projects: ["website"])

projects must name the key's project, otherwise the row is created but no download will ever include it.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/multilocale/phrases.rb', line 63

def upsert(phrases = nil, batch_size: DEFAULT_BATCH_SIZE, **attributes)
  rows =
    if phrases.nil?
      attributes.empty? ? [] : [attributes]
    else
      phrases.is_a?(Array) ? phrases : [phrases]
    end
  return [] if rows.empty?

  rows.each_slice(batch_size).flat_map do |batch|
    payload = batch.map { |row| Phrase.to_api(row) }
    # The API answers with a bare object for a single-element body and an
    # array otherwise, so both shapes have to be handled.
    result = @client.post("phrases", body: payload.size == 1 ? payload.first : payload)
    (result.is_a?(Array) ? result : [result]).map { |attributes| Phrase.new(attributes) }
  end
end