Skip to content

Commit

Permalink
Remove Translatable (#29)
Browse files Browse the repository at this point in the history
* [Translation] Remove translatable directive. Make Translate directive exclusive for FieldDefinition

* wip

* updated readme

* review feedback
  • Loading branch information
gmiserez authored Feb 9, 2023
1 parent 8a37de2 commit aa8d125
Show file tree
Hide file tree
Showing 20 changed files with 75 additions and 194 deletions.
28 changes: 0 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,34 +57,6 @@ With this we have registered the necessary objects to support translation on our

You can translate field values in several ways, listed below.

#### Translation on demand

A field can be made translatable. In this scenario, the field has two possible states: translated or not translated.
The consumer of the application decides whether he wants the translated state of the field or the non-translated state.
He does so by adding, or not adding, the field directive ```@translate``` to the field in his query.

```csharp
public class AddressType : ObjectType<Query>
{
protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
{
descriptor
.Field(c => c.Country) // the Country property is a Country enum
.Translatable("Ref/Aex/Countries")
.Type<NonNullType<StringType>>();
}
}
```

Querying this field will produce the following results:
```graphql
{
country // -> "CH"
countryLabel: country @translate // -> "Switzerland" if your Thread language is english
country_fr: country @translate(lang:"fr") // -> "Suisse"
}
```

#### Translation to a { key label } type

We can also rewrite our string/enum/other field to make it a `{ key label }` field.
Expand Down
20 changes: 9 additions & 11 deletions samples/StarWars.Tests/__snapshots__/schema.snap
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ type CreateReviewPayload {
"This resolver class extends all object types implementing ICharacter."
type Droid implements Character {
"The episodes the character appears in."
appearsIn: [TranslatedResourceOfEpisode!]! @translatable(resourceKeyPrefix: "Episodes", toCodeLabelItem: true) @translateEpisode
appearsIn: [TranslatedResourceOfEpisode!]! @translateEpisode(resourceKeyPrefix: "Episodes", toCodeLabelItem: true)
friends("Returns the elements in the list that come after the specified cursor." after: String "Returns the elements in the list that come before the specified cursor." before: String "Returns the first _n_ elements from the list." first: Int "Returns the last _n_ elements from the list." last: Int): FriendsConnection
"The height of the character."
height(unit: Unit = METERS): Float!
Expand Down Expand Up @@ -84,19 +84,19 @@ type FriendsEdge {
"This resolver class extends all object types implementing ICharacter."
type Human implements Character {
"The episodes the character appears in."
appearsIn: [TranslatedResourceOfEpisode!]! @translatable(resourceKeyPrefix: "Episodes", toCodeLabelItem: true) @translateEpisode
appearsIn: [TranslatedResourceOfEpisode!]! @translateEpisode(resourceKeyPrefix: "Episodes", toCodeLabelItem: true)
friends("Returns the elements in the list that come after the specified cursor." after: String "Returns the elements in the list that come before the specified cursor." before: String "Returns the first _n_ elements from the list." first: Int "Returns the last _n_ elements from the list." last: Int): FriendsConnection
"Color of the Human's hair"
hairColor: TranslatedResourceOfHairColor @translatable(resourceKeyPrefix: "HairColors", toCodeLabelItem: true) @translateHairColor
hairColor2: TranslatedResourceOfHairColor @translatable(resourceKeyPrefix: "HairColors", toCodeLabelItem: true) @translateHairColor
hairColor: TranslatedResourceOfHairColor @translateHairColor(resourceKeyPrefix: "HairColors", toCodeLabelItem: true)
hairColor2: TranslatedResourceOfHairColor @translateHairColor(resourceKeyPrefix: "HairColors", toCodeLabelItem: true)
"The height of the character."
height(unit: Unit = METERS): Float! @deprecated(reason: "invocations of this field will be tracked!")
"The planet the character is originally from."
homePlanet: String
"The unique identifier for the character."
id: Int!
"the Humans's marital status"
maritalStatus: TranslatedResourceOfMaritalStatus! @translatable(resourceKeyPrefix: "MaritalStatus", toCodeLabelItem: true) @translateMaritalStatus
maritalStatus: TranslatedResourceOfMaritalStatus! @translateMaritalStatus(resourceKeyPrefix: "MaritalStatus", toCodeLabelItem: true)
"The name of the character."
name: String!
}
Expand Down Expand Up @@ -378,14 +378,12 @@ directive @stream("Streamed when true." if: Boolean "The initial elements that s

directive @tracked repeatable on FIELD_DEFINITION

directive @translatable(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION
directive @translate(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION

directive @translate(language: String) on FIELD | FIELD_DEFINITION
directive @translateEpisode(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION

directive @translateEpisode(language: String) on FIELD | FIELD_DEFINITION
directive @translateHairColor(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION

directive @translateHairColor(language: String) on FIELD | FIELD_DEFINITION

directive @translateMaritalStatus(language: String) on FIELD | FIELD_DEFINITION
directive @translateMaritalStatus(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION

scalar UUID @specifiedBy(url: "https:\/\/tools.ietf.org\/html\/rfc4122")
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,4 @@ directive @defer("If this argument label has a value other than null, it will be
"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`."
directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! "Streamed when true." if: Boolean) on FIELD

directive @translatable(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION

directive @translate(language: String) on FIELD | FIELD_DEFINITION
directive @translate(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ interface ITranslation {
}

type Query {
bar: TranslatedResourceOfDummyEnum! @translatable(resourceKeyPrefix: "translation_path", toCodeLabelItem: true) @translateDummyEnum
bar: TranslatedResourceOfDummyEnum! @translateDummyEnum(resourceKeyPrefix: "translation_path", toCodeLabelItem: true)
foo: String!
}

Expand All @@ -26,8 +26,6 @@ directive @defer("If this argument label has a value other than null, it will be
"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`."
directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! "Streamed when true." if: Boolean) on FIELD

directive @translatable(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION
directive @translate(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION

directive @translate(language: String) on FIELD | FIELD_DEFINITION

directive @translateDummyEnum(language: String) on FIELD | FIELD_DEFINITION
directive @translateDummyEnum(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ public async Task Translate_WithNonNullableEnum_ShouldTranslateProperly()
.AddSingleton<IResourcesProviderAdapter>(new EvergreenResourcesProviderAdapter())
.AddGraphQL()
.AddDirectiveType<TranslateDirectiveType<DummyValues>>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("foo")
.Resolver(keys)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public void Translate_AsNonNullable_ShouldAddBothDirectives()
//Act
ISchema schema = SchemaBuilder.New()
.AddDirectiveType<TranslateDirectiveType<DummyValues>>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(keys)
Expand All @@ -48,7 +47,6 @@ public void Translate_AsNullable_ShouldAddBothDirectives()
//Act
ISchema schema = SchemaBuilder.New()
.AddDirectiveType<TranslateDirectiveType<DummyValues>>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(keys)
Expand Down Expand Up @@ -76,7 +74,6 @@ public void Translated_RmsNodePathOk_ShouldAddBothDirectives()
//Act
ISchema schema = SchemaBuilder.New()
.AddDirectiveType<TranslateDirectiveType>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(keys)
Expand Down Expand Up @@ -114,7 +111,6 @@ public async Task Translated_StringValue_ShouldTranslate(string culture)
ISchema schema = SchemaBuilder.New()
.AddServices(services)
.AddDirectiveType<TranslateDirectiveType>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(key)
Expand Down Expand Up @@ -163,7 +159,6 @@ public async Task Translated_ArrayOfStringValues_ShouldTranslate(string culture)
ISchema schema = SchemaBuilder.New()
.AddServices(services)
.AddDirectiveType<TranslateDirectiveType>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(keys)
Expand Down Expand Up @@ -194,7 +189,6 @@ public void TranslateArray_RmsNodePathOk_ShouldAddBothDirectives()
//Act
ISchema schema = SchemaBuilder.New()
.AddDirectiveType<TranslateDirectiveType>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(keys)
Expand All @@ -214,7 +208,6 @@ public void TranslateArrayOfT_RmsNodePathOk_ShouldAddBothDirectives()
//Act
ISchema schema = SchemaBuilder.New()
.AddDirectiveType<TranslateDirectiveType<DummyValues>>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(keys)
Expand Down Expand Up @@ -252,7 +245,6 @@ public async Task TranslateArrayT_RmsNodePathOk_ShouldTranslate(string culture)
ISchema schema = SchemaBuilder.New()
.AddServices(services)
.AddDirectiveType<TranslateDirectiveType<DummyValues>>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(keys)
Expand Down Expand Up @@ -301,7 +293,6 @@ public async Task TranslateArray_RmsNodePathOk_ShouldTranslate(string culture)
ISchema schema = SchemaBuilder.New()
.AddServices(services)
.AddDirectiveType<TranslateDirectiveType>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(keys)
Expand Down Expand Up @@ -338,7 +329,6 @@ public async Task Translated_ArrayNull_ShouldReturnNull()
ISchema schema = SchemaBuilder.New()
.AddServices(services.BuildServiceProvider())
.AddDirectiveType<TranslateDirectiveType>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(keys)
Expand Down Expand Up @@ -368,7 +358,6 @@ public async Task Translated_UnsupportedType_ShouldReturnNull()
ISchema schema = SchemaBuilder.New()
.AddServices(services.BuildServiceProvider())
.AddDirectiveType<TranslateDirectiveType>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(new Dummy())
Expand Down Expand Up @@ -399,7 +388,6 @@ ISchema buildSchema() =>
.New()
.AddServices(services.BuildServiceProvider())
.AddDirectiveType<TranslateDirectiveType>()
.AddDirectiveType<TranslatableDirectiveType>()
.AddQueryType(d =>
d.Field("myField")
.Resolve(new[] { "foo", "bar" })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ public void RegisterTranslation_WithBuilder_ShouldAddBothTranslationDirectives()
ISchema schema = builder.Create();
schema.DirectiveTypes.Should().Contain(d => d.RuntimeType
== typeof(TranslateDirective<string>));
schema.DirectiveTypes.Should().Contain(d => d.RuntimeType
== typeof(TranslatableDirective));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class TranslateDirectiveTypeTests
public void UpdateResult_StringValueAndLanguageSet_ReturnsStringValue()
{
//Arrange
var directive = new TranslatableDirective("myNodePath", false);
var directive = new TranslateDirective("myNodePath", false);
string value = "myValue";

IMiddlewareContext context = BuildMockContext(
Expand All @@ -35,7 +35,7 @@ public void UpdateResult_StringValueAndLanguageSet_ReturnsStringValue()
public void UpdateResult_StringValueToCodeLabelItem_ReturnsStringValue()
{
//Arrange
var directive = new TranslatableDirective("myNodePath", toCodeLabelItem: true);
var directive = new TranslateDirective("myNodePath", toCodeLabelItem: true);
string value = "myValue";

IMiddlewareContext context = BuildMockContext(
Expand All @@ -62,7 +62,7 @@ public void UpdateResult_StringValueToCodeLabelItem_ReturnsStringValue()
public void UpdateResult_NullableIntValue_ReturnsStringValue(object value)
{
//Arrange
var directive = new TranslatableDirective("myNodePath", false);
var directive = new TranslateDirective("myNodePath", false);

IMiddlewareContext context = BuildMockContext(
value,
Expand All @@ -77,7 +77,7 @@ public void UpdateResult_NullableIntValue_ReturnsStringValue(object value)
public void UpdateResult_StringValueMissingKey_ReturnsKey()
{
//Arrange
var directive = new TranslatableDirective("myNodePath", false);
var directive = new TranslateDirective("myNodePath", false);
string value = "myValue";

IMiddlewareContext context = BuildMockContext(
Expand All @@ -95,7 +95,7 @@ public void UpdateResult_StringValueMissingKey_ReturnsKey()
public void UpdateResult_EnumerableStringValue_ReturnsStringValue()
{
//Arrange
var directive = new TranslatableDirective("myNodePath", false);
var directive = new TranslateDirective("myNodePath", false);
IEnumerable<string> value = new List<string>
{
"myValue1",
Expand Down Expand Up @@ -127,7 +127,7 @@ public void UpdateResult_EnumerableStringValue_ReturnsStringValue()
public void UpdateResult_ArrayEmpty_ShouldNotThrowException()
{
//Arrange
var directive = new TranslatableDirective("myNodePath", false);
var directive = new TranslateDirective("myNodePath", false);
IEnumerable<string> value = new List<string>();

IMiddlewareContext context = BuildMockContext(
Expand All @@ -149,7 +149,7 @@ public void UpdateResult_ArrayEmpty_ShouldNotThrowException()
public void UpdateResult_EnumerableStringValueWithSomeMissingKeys_ReturnsStringValueAndKeysWhenValueIsMissing()
{
//Arrange
var directive = new TranslatableDirective("myNodePath", false);
var directive = new TranslateDirective("myNodePath", false);
IEnumerable<string> resolverResult = new List<string>
{
"myValue1",
Expand Down Expand Up @@ -183,7 +183,7 @@ public void UpdateResult_EnumerableStringValueWithSomeMissingKeys_ReturnsStringV
public void UpdateResult_EnumValue_ReturnsStringValue()
{
//Arrange
var directive = new TranslatableDirective("myNodePath", false);
var directive = new TranslateDirective("myNodePath", false);
TestEnum value = TestEnum.SecondEnum;

IMiddlewareContext context = BuildMockContext(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
}

type ObjectType {
myField: TranslatedResourceOfDummyValues! @translatable(resourceKeyPrefix: "prefix", toCodeLabelItem: true) @translateDummyValues
myField: TranslatedResourceOfDummyValues! @translateDummyValues(resourceKeyPrefix: "prefix", toCodeLabelItem: true)
}

type TranslatedResourceOfDummyValues {
Expand All @@ -24,6 +24,4 @@ directive @defer("If this argument label has a value other than null, it will be
"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`."
directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! "Streamed when true." if: Boolean) on FIELD

directive @translatable(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION

directive @translateDummyValues(language: String) on FIELD | FIELD_DEFINITION
directive @translateDummyValues(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
}

type ObjectType {
myField: TranslatedResourceOfDummyValues @translatable(resourceKeyPrefix: "prefix", toCodeLabelItem: true) @translateDummyValues
myField: TranslatedResourceOfDummyValues @translateDummyValues(resourceKeyPrefix: "prefix", toCodeLabelItem: true)
}

type TranslatedResourceOfDummyValues {
Expand All @@ -24,6 +24,4 @@ directive @defer("If this argument label has a value other than null, it will be
"The `@stream` directive may be provided for a field of `List` type so that the backend can leverage technology such as asynchronous iterators to provide a partial list in the initial response, and additional list items in subsequent responses. `@include` and `@skip` take precedence over `@stream`."
directive @stream("If this argument label has a value other than null, it will be passed on to the result of this stream directive. This label is intended to give client applications a way to identify to which fragment a streamed result belongs to." label: String "The initial elements that shall be send down to the consumer." initialCount: Int! "Streamed when true." if: Boolean) on FIELD

directive @translatable(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION

directive @translateDummyValues(language: String) on FIELD | FIELD_DEFINITION
directive @translateDummyValues(resourceKeyPrefix: String! toCodeLabelItem: Boolean!) on FIELD_DEFINITION
Loading

0 comments on commit aa8d125

Please sign in to comment.