Skip to content

Commit

Permalink
test: add readme fixtures
Browse files Browse the repository at this point in the history
  • Loading branch information
sheerlox committed Nov 21, 2023
1 parent 5c40b74 commit 138d89d
Show file tree
Hide file tree
Showing 2 changed files with 280 additions and 0 deletions.
123 changes: 123 additions & 0 deletions tests/fixtures/readme/gettext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Gettext

[![hex.pm badge](https://img.shields.io/badge/Package%20on%20hex.pm-informational)](https://hex.pm/packages/gettext)
[![Documentation badge](https://img.shields.io/badge/Documentation-ff69b4)][docs-gettext]
![CI badge](https://github.com/elixir-gettext/gettext/workflows/CI/badge.svg)

Gettext is an **internationalization** (i18n) and **localization** (l10n) system commonly used for writing multilingual programs. Gettext is a standard for i18n in different communities, meaning there is a great set of tooling for developers and translators. This project is an implementation of the Gettext system in Elixir.

## Installation

Add `:gettext` to your list of dependencies in `mix.exs` (use `$ mix hex.info gettext` to find the latest version):

```elixir
defp deps do
[
{:gettext, ">= 0.0.0"}
]
end
```

Documentation for `Gettext` is [available on Hex][docs-gettext].

## Usage

To use Gettext, define a Gettext module:

```elixir
defmodule MyApp.Gettext do
use Gettext, otp_app: :my_app
end
```

and invoke the Gettext API, which consists of the `*gettext` macros:

```elixir
import MyApp.Gettext

# Simple message
gettext("Here is one string to translate")

# Plural message
number_of_apples = 4
ngettext("The apple is ripe", "The apples are ripe", number_of_apples)

# Domain-based message
dgettext("errors", "Here is an error message to translate")
```

Messages in Gettext are stored in Portable Object files (`.po`). Such files must be placed at `priv/gettext/LOCALE/LC_MESSAGES/DOMAIN.po`, where `LOCALE` is the locale and `DOMAIN` is the domain (the default domain is called `default`).

For example, the message to `pt_BR` of the first two `*gettext` calls in the snippet above must be placed in the `priv/gettext/pt_BR/LC_MESSAGES/default.po` file with contents:

```pot
msgid "Here is one string to translate"
msgstr "Aqui está um texto para traduzir"
msgid "Here is the string to translate"
msgid_plural "Here are the strings to translate"
msgstr[0] "Aqui está o texto para traduzir"
msgstr[1] "Aqui estão os textos para traduzir"
```

`.po` are text-based files and can be edited directly by translators. Some may even use existing tools for managing them, such as [Poedit][poedit] or [poeditor.com][poeditor.com].

Finally, because messages are based on strings, your source code does not lose readability as you still see literal strings, like `gettext("here is an example")`, instead of paths like `translate("some.path.convention")`.

Read the [documentation for the `Gettext` module][docs-gettext-module] for more information on locales, interpolation, pluralization, and other features.

## Workflow

Gettext is able to automatically extract messages from your source code, alleviating developers and translators from the repetitive and error-prone work of maintaining message files.

When extracted from source, Gettext places messages into `.pot` files, which are template files. You can then merge those templates files into message files for each specific locale your application is being currently translated to.

In other words, the typical workflow looks like this:

1. Add `gettext` calls to your source code. No need to touch message files
at this point as Gettext will return the given string if no message is
available:

```elixir
gettext("Welcome back!")
```

2. Once changes to the source are complete, automatically sync all existing entries to `.pot` (template files) in `priv/gettext` by running:

```bash
mix gettext.extract
```

3. You can then merge `.pot` files into locale-specific `.po` files:

```bash
# Merge .pot into all locales
mix gettext.merge priv/gettext

# Merge .pot into one specific locale
mix gettext.merge priv/gettext --locale en
```

It is also possible to both extract and merge messages in one step with `mix gettext.extract --merge`.

## License

Copyright 2015 Plataformatec
Copyright 2020 Dashbit

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:

> <http://www.apache.org/licenses/LICENSE-2.0>

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

[docs-gettext]: http://hexdocs.pm/gettext
[docs-gettext-module]: http://hexdocs.pm/gettext/Gettext.html
[poedit]: http://poedit.net/
[poeditor.com]: https://poeditor.com
157 changes: 157 additions & 0 deletions tests/fixtures/readme/jason.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Jason

A blazing fast JSON parser and generator in pure Elixir.

The parser and generator are at least twice as fast as other Elixir/Erlang libraries
(most notably `Poison`).
The performance is comparable to `jiffy`, which is implemented in C as a NIF.
Jason is usually only twice as slow.

Both parser and generator fully conform to
[RFC 8259](https://tools.ietf.org/html/rfc8259) and
[ECMA 404](http://www.ecma-international.org/publications/standards/Ecma-404.htm)
standards. The parser is tested using [JSONTestSuite](https://github.com/nst/JSONTestSuite).

## Installation

The package can be installed by adding `jason` to your list of dependencies
in `mix.exs`:

```elixir
def deps do
[{:jason, "~> 1.4"}]
end
```

## Basic Usage

``` elixir
iex(1)> Jason.encode!(%{"age" => 44, "name" => "Steve Irwin", "nationality" => "Australian"})
"{\"age\":44,\"name\":\"Steve Irwin\",\"nationality\":\"Australian\"}"

iex(2)> Jason.decode!(~s({"age":44,"name":"Steve Irwin","nationality":"Australian"}))
%{"age" => 44, "name" => "Steve Irwin", "nationality" => "Australian"}
```

Full documentation can be found at [https://hexdocs.pm/jason](https://hexdocs.pm/jason).

## Use with other libraries

### Postgrex

Versions starting at 0.14.0 use `Jason` by default. For earlier versions, please refer to
[previous versions of this document](https://github.com/michalmuskala/jason/tree/v1.1.2#postgrex).

### Ecto

Versions starting at 3.0.0 use `Jason` by default. For earlier versions, please refer to
[previous versions of this document](https://github.com/michalmuskala/jason/tree/v1.1.2#ecto).

### Plug (and Phoenix)

Phoenix starting at 1.4.0 uses `Jason` by default. For earlier versions, please refer to
[previous versions of this document](https://github.com/michalmuskala/jason/tree/v1.1.2#plug-and-phoenix).

### Absinthe

You need to pass the `:json_codec` option to `Absinthe.Plug`

```elixir
# When called directly:
plug Absinthe.Plug,
schema: MyApp.Schema,
json_codec: Jason

# When used in phoenix router:
forward "/api",
to: Absinthe.Plug,
init_opts: [schema: MyApp.Schema, json_codec: Jason]
```

## Benchmarks

Detailed benchmarks (including memory measurements):
https://gist.github.com/michalmuskala/4d64a5a7696ca84ac7c169a0206640d5

HTML reports for the benchmark (only performance measurements):
http://michal.muskala.eu/jason/decode.html and http://michal.muskala.eu/jason/encode.html

### Running

Benchmarks against most popular Elixir & Erlang json libraries can be executed after
going into the `bench/` folder and then executing `mix bench.encode` and `mix bench.decode`.
A HTML report of the benchmarks (after their execution) can be found in
`bench/output/encode.html` and `bench/output/decode.html` respectively.

## Differences to Poison

Jason has a couple feature differences compared to Poison.

* Jason follows the JSON spec more strictly, for example it does not allow
unescaped newline characters in JSON strings - e.g. `"\"\n\""` will
produce a decoding error.
* no support for decoding into data structures (the `as:` option).
* no built-in encoders for `MapSet`, `Range` and `Stream`.
* no support for encoding arbitrary structs - explicit implementation
of the `Jason.Encoder` protocol is always required.
* different pretty-printing customisation options (default `pretty: true` works the same)

### Encoders

If you require encoders for any of the unsupported collection types, I suggest
adding the needed implementations directly to your project:

```elixir
defimpl Jason.Encoder, for: [MapSet, Range, Stream] do
def encode(struct, opts) do
Jason.Encode.list(Enum.to_list(struct), opts)
end
end
```

If you need to encode some struct that does not implement the protocol,
if you own the struct, you can derive the implementation specifying
which fields should be encoded to JSON:

```elixir
@derive {Jason.Encoder, only: [....]}
defstruct # ...
```

It is also possible to encode all fields, although this should be
used carefully to avoid accidentally leaking private information
when new fields are added:

```elixir
@derive Jason.Encoder
defstruct # ...
```

Finally, if you don't own the struct you want to encode to JSON,
you may use `Protocol.derive/3` placed outside of any module:

```elixir
Protocol.derive(Jason.Encoder, NameOfTheStruct, only: [...])
Protocol.derive(Jason.Encoder, NameOfTheStruct)
```

## Injecting an already encoded JSON inside a to-be-encoded structure

If parts of the to-be-encoded structure are already JSON-encoded, you can
use `Jason.Fragment` to mark the parts as already encoded, and avoid a
decoding/encoding roundtrip.

```elixir
already_encoded_json = Jason.encode!(%{hello: "world"})
Jason.encode!(%{foo: Jason.Fragment.new(already_encoded_json)})
```

This feature is especially useful if you need to cache a part of the JSON,
or if it is already provided by another system (e.g. `jsonb_agg` with Postgres).

## License

Jason is released under the Apache License 2.0 - see the [LICENSE](LICENSE) file.

Some elements of tests and benchmarks have their origins in the
[Poison library](https://github.com/devinus/poison) and were initially licensed under [CC0-1.0](https://creativecommons.org/publicdomain/zero/1.0/).

0 comments on commit 138d89d

Please sign in to comment.